#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