Основываясь на ответе на этот вопрос, я написал скрипт, совместимый с более старой версией SQL Server, поскольку STRING_AGG
был представлен только в SQL Server 2017 ...
Declare @SQLQuery Nvarchar(4000)= 'Select col_a,col_b,col_c from My_main_table order by col_b ASC,col_a DESC'
Declare @TableName varchar(50)= 'TMP_MyTest'
Declare @createTmpStr Nvarchar(4000)
-- End Debug
Declare @CLUST_INDEX Nvarchar(4000)=''
IF OBJECT_ID('tempdb..#ResultStructure') IS NOT NULL
DROP TABLE #ResultStructure
-- NEED TO TEST BECAUSE I READ:
-- it is known, that sys.sp_describe_first_result_set fails to retrieve the metadata for a stored procedure when a temp table is used in it.
create table #ResultStructure (is_hidden bit NOT NULL
, column_ordinal int NOT NULL
, name sysname NULL
, is_nullable bit NOT NULL
, system_type_id int NOT NULL
, system_type_name nvarchar(256) NULL
, max_length smallint NOT NULL
, precision tinyint NOT NULL
, scale tinyint NOT NULL
, collation_name sysname NULL
, user_type_id int NULL
, user_type_database sysname NULL
, user_type_schema sysname NULL
, user_type_name sysname NULL
, assembly_qualified_type_name nvarchar(4000)
, xml_collection_id int NULL
, xml_collection_database sysname NULL
, xml_collection_schema sysname NULL
, xml_collection_name sysname NULL
, is_xml_document bit NOT NULL
, is_case_sensitive bit NOT NULL
, is_fixed_length_clr_type bit NOT NULL
, source_server sysname NULL
, source_database sysname NULL
, source_schema sysname NULL
, source_table sysname NULL
, source_column sysname NULL
, is_identity_column bit NULL
, is_part_of_unique_key bit NULL
, is_updateable bit NULL
, is_computed_column bit NULL
, is_sparse_column_set bit NULL
, ordinal_in_order_by_list smallint NULL
, order_by_list_length smallint NULL
, order_by_is_descending smallint NULL
, tds_type_id int NOT NULL
, tds_length int NOT NULL
, tds_collation_id int NULL
, tds_collation_sort_id tinyint NULL
);
Insert #ResultStructure
exec sys.sp_describe_first_result_set @Tsql=@SqlQuery;
SET @createTmpStr=''
Select @createTmpStr= @createTmpStr +Fields
from (
select
case when column_ordinal = 1 then 'create table ' + @Tablename + '(' else ', ' end
+ QUOTENAME (name) + ' ' + system_type_name
+ case when column_ordinal = max(column_ordinal) over () then ');' else ''
end as Fields
from #ResultStructure) T
До тех пор, пока все не будет работать нормально ... Теперь мне нужно убедиться, что данные, которые будут вставлены в таблицу tmp (@TableName), будут соответствовать порядку, указанному в предложении @SQLQuery. Для этого я добавил следующий фрагмент, который я намереваюсь добавить в @createTmpStr, найденный выше.
IF EXISTS (SELECT 1 FROM #ResultStructure WHERE ordinal_in_order_by_list is not null)
Select @CLUST_INDEX= @CLUST_INDEX +Fields
from (
select TOP 100 PERCENT
case when ordinal_in_order_by_list = 1 then 'CREATE CLUSTERED INDEX IDX_' + @Tablename + ' ON '+ @Tablename +'(' else ', ' end
+ name + ' ' + case when order_by_list_length=0 then 'ASC' else 'DESC' end
+ case when ordinal_in_order_by_list = max(ordinal_in_order_by_list) over () then ');' else ''
end as Fields
from #ResultStructure
where ordinal_in_order_by_list is not null
ORDER BY ordinal_in_order_by_list) T
SELECT @CLUST_INDEX
Мне трудно понять, что упорядочение в подзапросе работает нормально, но вывод в переменной @CLUST_INDEX неправильно строит строку ...
По какой-то причине похоже, что она все еще использует поле column_ordinal при построении строки ...
Полученная строка выглядит следующим образом это
, col_a DESC);CREATE CLUSTERED INDEX IDX_TMP_MyTest ON TMP_MyTest(col_b ASC
Я пытаюсь понять и найти решение этой проблемы.