Выберите имена столбцов и верхние 1 записи вместе, динамически

#sql #sql-server #tsql #dynamic

#sql #sql-сервер #tsql #динамический

Вопрос:

Я пытался выбрать значение верхнего столбца 1 из таблицы, чтобы получить представление о данных на основе выходных данных (т. Е. Эквивалентно,

   SELECT c.name FROM st.Name
  

Этот запрос извлекает имена столбцов и их тип данных вместе с таблицами, в которых они находятся. Я ищу дополнительный столбец, который показывает верхнюю запись 1 из столбцов.

 SELECT 
st.name 'Table Name', 
c.name 'Column Name', 
t.name 'Data Type'

FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id 
LEFT OUTER JOIN sys.tables st ON st.object_id = i.object_id 
  

Я пытался использовать динамический sql, но поскольку он должен заключать имя таблицы в одинарные кавычки в виде строки, это не сработало; когда я пытаюсь избежать этого, он просто отображает объявленную переменную.
Любая идея высоко ценится. Спасибо

Комментарии:

1. Поделитесь с нами созданным вами динамическим SQL, и мы поможем вам исправить это.

Ответ №1:

Таким образом, способ, которым это работает, в основном создает кучу выборок, таких как:

 SELECT 'dbo' AS [Schema Name]
     , 'Table1' AS [Table Name]
     , 'Id' AS [Column Name]
     , 'bigint' AS [Data Type]
     , (SELECT TOP 1 CONVERT(NVARCHAR(MAX), Id) FROM [dbo].[Table1]) AS [Top 1 Value] 

UNION ALL

-- Another table
  

Значения преобразуются в NVARCHAR(MAX) потому что тип столбца в объединении должен совпадать, и я думаю, что это лучший выбор.

Далее:

 DECLARE @query NVARCHAR(MAX) = ''
SELECT @Query  = 
'SELECT '   ''''   sch.name   ''''   ' AS [Schema Name],'   CHAR(13) CHAR(10)
            ''''   st.name    ''''   ' AS [Table Name],'   CHAR(13) CHAR(10)
            ''''   c.name     ''''   ' AS [Column Name],'   CHAR(13) CHAR(10)
            ''''   t.name     ''''   ' AS [Data Type],'   CHAR(13) CHAR(10)
            '(SELECT TOP 1 CONVERT(NVARCHAR(MAX), '   c.name   ') FROM '   QUOTENAME(sch.name)   '.'   QUOTENAME(st.name)   ') AS [Top 1 Value] '   CHAR(13) CHAR(10)
            'UNION ALL' CHAR(13) CHAR(10)
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id 
JOIN sys.tables st ON st.object_id = i.object_id 
JOIN sys.schemas sch ON sch.schema_id = st.schema_id

-- Get rid of trailing UNION ALL
SET @Query = LEFT(@Query, LEN(@Query) - LEN('UNION ALLxx'))

PRINT @query
EXEC sp_executesql @query
  

Сначала рассмотрите возможность запуска с TOP 10 или чем-то подобным, чтобы убедиться, что он дает правильные результаты.

Комментарии:

1. возможно, вам потребуется обернуть столбец SELECT в оператор case, чтобы исключить неконвертируемые типы данных, например. изображение, xml и т. Д

Ответ №2:

вы могли бы использовать цикл while с общим sql

 --drop table #temp

SELECT 
    CONCAT(s.name,'.',st.name) 'Table Name', 
    c.name 'Column Name', 
    t.name 'Data Type',
    CAST(null AS datetime) as IND,
    cast('' AS varchar(max)) data
    INTO #temp
FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id 
INNER JOIN sys.tables st ON st.object_id = i.object_id
INNER JOIN sys.schemas s ON s.schema_id = st.schema_id



declare 
@TableName varchar(255),
@ColumnName Varchar(255),
@sql varchar(max)

WHILE (SELECT count(*) FROM #temp where IND is null) > 0
begin

        SELECT TOP 1 
            @TableName = [Table Name]
            ,@ColumnName = [Column Name]
        FROM #temp
        WHERE IND IS NULL

        SET @sql = 
        'update  #temp 
         set data  = (SELECT top 1 ['   @ColumnName   '] from '   @TableName   '),
         IND = getdate()
         where [Table Name] = '''   @TableName   ''' and [Column Name] = '''    @ColumnName   ''''

        exec(@sql)
end


SELECT * 
FROM #temp