我需要从使用#temp表切换到@table变量,以便我可以在函数中使用它。
我的查询使用insert到#temp(来自多个表),如下所示:
SELECT
a.col1,
a.col2,
b.col1...
INTO #temp
FROM ...
是否有一种简单的方法可以找到#temp表中列的数据类型,这样我就可以使用与#temp相同的列和数据类型创建@table变量?
答案 0 :(得分:112)
您需要确保sp_help
在表所在的同一数据库(tempdb)中运行。您可以通过直接为呼叫添加前缀来执行此操作:
EXEC tempdb.dbo.sp_help @objname = N'#temp';
或者通过为tempdb.sys.columns
添加联接前缀:
SELECT [column] = c.name,
[type] = t.name, c.max_length, c.precision, c.scale, c.is_nullable
FROM tempdb.sys.columns AS c
INNER JOIN tempdb.sys.types AS t
ON c.system_type_id = t.system_type_id
AND t.system_type_id = t.user_type_id
WHERE [object_id] = OBJECT_ID(N'tempdb.dbo.#temp');
这不能为你处理好事,比如调整varchar的max_length与nvarchar不同,但这是一个好的开始。
在SQL Server 2012或更高版本中,您可以使用新的DMF来描述结果集,该结果集可以解决该问题(并且还可以为您组装max_length / precision / scale)。但是它不支持#temp表,所以只需要在没有INTO 的情况下注入查询:
SELECT name, system_type_name, is_nullable
FROM sys.dm_exec_describe_first_result_set(N'SELECT
a.col1,
a.col2,
b.col1...
--INTO #temp
FROM ...;',NULL,1);
答案 1 :(得分:9)
接受的答案没有给出数据类型。使用sys.types加入tempdb.sys.columns会给出答案注释中提到的数据类型。但是加入system_type_id会产生一个数据类型为“sysname”的额外行。相反,“user_type_id”给出了下面给出的确切解决方案。
SELECT cols.NAME
,ty.NAME
FROM tempdb.sys.columns cols
JOIN sys.types ty ON cols.user_type_id = ty.user_type_id
WHERE object_id = OBJECT_ID('tempdb..#temp')
答案 2 :(得分:7)
您需要限定sp_help进程以从tempdb数据库运行以获取有关哈希表的详细信息,因为这是哈希表实际存储的位置。如果您尝试从其他数据库运行sp_help,则会收到该数据库中不存在该表的错误。
如果您的查询在tempdb之外执行,我认为是,您可以运行以下命令:
exec tempdb..sp_help #temp
此过程的一个好处是它包含您的列数据类型的文本说明。这使得复制和粘贴到另一个查询中非常容易,例如如果您正在尝试使用临时表的定义来创建表变量。
您可以在Syscolumns表中找到相同的信息,但它会为您提供自己必须映射的类型的数字标识符。使用sp_help将为您节省一步。
答案 3 :(得分:3)
您要做的是获取有关要查询的列的系统类型的信息。
对于SQL Server 2012 and later
,您可以使用sys.dm_exec_describe_first_result_set功能。它返回有关列的非常详细的信息,system_type_column
包含完整的系统类型定义(准备在表定义中使用):
例如:
SELECT *
FROM [sys].[dm_exec_describe_first_result_set] (N'SELECT object_id, name, type_desc FROM sys.indexes', null, 0);
答案 4 :(得分:3)
其他答案将为您提供所需的信息,但仍需要您在定义表变量时全部输入。
以下TSQL将允许您快速生成任何给定表的表变量定义。
这可以节省大量时间,而不是手动输入表定义,如:
table(Field1Name nvarchar(4), Field2Name nvarchar(20), Field3Name int
, Field4Name numeric(28,12))
TSQL:
select top 10 *
into #temp
from db.dbo.myTable
declare @tableName nvarchar(max)
set @tableName = '#temp'
use tempdb
declare @tmp table(val nvarchar(max))
insert into @tmp
select case data_type
when 'binary' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
when 'char' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
when 'datetime2' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + CAST(DATETIME_PRECISION as nvarchar(max)) + ')'
when 'datetimeoffset' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + CAST(DATETIME_PRECISION as nvarchar(max)) + ')'
when 'decimal' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(NUMERIC_PRECISION as nvarchar(max)) + ',' + cast(NUMERIC_SCALE as nvarchar(max)) + ')'
when 'nchar' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
when 'numeric' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(NUMERIC_PRECISION as nvarchar(max)) + ',' + cast(NUMERIC_SCALE as nvarchar(max)) + ')'
when 'nvarchar' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
when 'time' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + CAST(DATETIME_PRECISION as nvarchar(max)) + ')'
when 'varbinary' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
when 'varchar' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
-- Most standard data types follow the pattern in the other section.
-- Non-standard datatypes include: binary, char, datetime2, datetimeoffset, decimal, nvchar, numeric, nvarchar, time, varbinary, and varchar
else COLUMN_NAME + ' ' + DATA_TYPE
end + case when IS_NULLABLE <> 'YES' then ' NOT NULL' else '' end 'dataType'
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME like @tableName + '%'
declare @result nvarchar(max)
set @result = ''
select @result = @result + [val] + N','
from @tmp
where val is not null
set @result = substring(@result, 1, (LEN(@result)-1))
-- The following will replce '-1' with 'max' in order to properly handle nvarchar(max) columns
set @result = REPLACE(@result, '-1', 'max')
select @result
输出:
Field1Name nvarchar(4), Field2Name nvarchar(20), Field3Name int
, Field4Name numeric(28,12)
答案 5 :(得分:2)
是的,临时表的数据类型将是您选择并插入其中的列的数据类型。因此,只需查看select语句,并根据您选择的列确定每种数据类型。
答案 6 :(得分:2)
获取具有数据类型的列名称使用此
EXEC tempdb.dbo.sp_help N'#temp';
或 要仅获取列名称以使用此
SELECT *
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID(N'tempdb..#temp');
答案 7 :(得分:1)
我会去懒惰路线并使用
use tempdb
GO
EXECUTE sp_help #temp
答案 8 :(得分:1)
查找SQL临时表的数据类型
方法1 –使用SP_HELP
EXEC TempDB..SP_HELP #TempTable;
注意-
在表格结构中,表格名称显示类似于“ #TempTable ________________________________________________________________________________________________________________________ 0000000004CB”。实际上,每个临时表名称的总长度为128。为了在多个会话中以不同的方式处理同一个临时表名称,SQL Server将在之间和字母数字末尾自动添加一些下划线。
方法2 –使用SP_COLUMNS
EXEC TempDB..SP_COLUMNS '#TempTable';
方法3 –使用系统表,例如INFORMATION_SCHEMA.COLUMNS,SYS.COLUMNS,SYS.TABLES
SELECT * FROM TempDB.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME IN (
SELECT NAME FROM TempDB.SYS.TABLES WHERE OBJECT_ID=OBJECT_ID('TempDB.dbo.#TempTable')
);
GO
SELECT * FROM TempDB.SYS.COLUMNS WHERE OBJECT_ID=OBJECT_ID('TempDB.dbo.#TempTable');
GO
SELECT * FROM TempDB.SYS.TABLES WHERE OBJECT_ID=OBJECT_ID('TempDB.dbo.#TempTable');
GO