Sql server 每行连接任意长度的列
如何连接每行任意长度的列?我尝试了以下操作,但函数as需要指定列名:Sql server 每行连接任意长度的列,sql-server,tsql,Sql Server,Tsql,如何连接每行任意长度的列?我尝试了以下操作,但函数as需要指定列名: SELECT CONCAT([C1], [C2], ...) FROM [dbo.table]; 如何在不明确指定每个列名的情况下获得相同的结果?要在任意表中包含所有列,请执行以下操作: DECLARE @Columns nvarchar(MAX) SELECT @Columns = ISNULL(@Columns + ',','') + COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMN
SELECT CONCAT([C1], [C2], ...) FROM [dbo.table];
如何在不明确指定每个列名的情况下获得相同的结果?要在任意表中包含所有列,请执行以下操作:
DECLARE @Columns nvarchar(MAX)
SELECT @Columns = ISNULL(@Columns + ',','') + COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TableName' AND TABLE_SCHEMA='dbo'
DECLARE @sql nvarchar(MAX)
SET @sql = N'SELECT CONCAT('+@Columns+')
FROM dbo.TableName'
EXEC sp_executesql @sql
您需要使用动态SQL。您可以查询系统目录视图
sys.columns
以获取列名,然后使用给定要执行的最终SQL:
DECLARE @TableName SYSNAME = 'dbo.YourTable';
DECLARE @SQL NVARCHAR(MAX) = 'SELECT CONCAT(' +
STUFF(( SELECT ',' + QUOTENAME(c.Name)
FROM sys.columns c
WHERE [object_id] = OBJECT_ID(@TableName)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '') + ')
FROM ' + @TableName + ';';
EXECUTE sp_executesql @SQL;
附录 如果要分隔列,可以在创建列列表时添加进一步的连接:
DECLARE @TableName SYSNAME = 'dbo.YourTable',
@Delimiter VARCHAR(10) = ', ';
DECLARE @SQL NVARCHAR(MAX) = 'SELECT CONCAT(' +
STUFF(( SELECT ',''' + @Delimiter + ''',' + QUOTENAME(c.Name)
FROM sys.columns c
WHERE [object_id] = OBJECT_ID(@TableName)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, LEN(@Delimiter) + 5, '') + ')
FROM ' + @TableName + ';';
EXECUTE sp_executesql @SQL;
附录2
要避免在值为null时添加分隔符,例如,而不是以以下形式结束:
1,,,2,3
你只需要
1,2,3
在生成如下查询之前,您需要稍微修改逻辑:
CONCAT([C1], ',', [C2], ',', [C3])
相反,您希望:
CONCAT([C1], ',' + [C2], ',' + [C3])
由于您现在使用的是,“+[C2]
如果[C2]
为空,则结果将为空,因此将删除分隔符:
DECLARE @TableName SYSNAME = 'dbo.YourTable',
@Delimiter VARCHAR(10) = ', ';
DECLARE @SQL NVARCHAR(MAX) = 'SELECT CONCAT(' +
STUFF(( SELECT ',''' + @Delimiter + ''' + ' + QUOTENAME(c.Name)
FROM sys.columns c
WHERE [object_id] = OBJECT_ID(@TableName)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, LEN(@Delimiter) + 7, '') + ')
FROM ' + @TableName + ';';
EXECUTE sp_executesql @SQL;
附录3 要删除第一列,可以使用
sys.columns
系统目录视图上的ROW\u NUMBER()
,然后排除第一列:
DECLARE @TableName SYSNAME = 'dbo.YourTable',
@Delimiter VARCHAR(10) = ', ';
DECLARE @SQL NVARCHAR(MAX) = 'SELECT CONCAT(' +
STUFF(( SELECT ',''' + @Delimiter + ''' + ' + QUOTENAME(c.Name)
FROM ( SELECT name,
RowNumber = ROW_NUMBER() OVER(ORDER BY column_id)
FROM sys.columns c
WHERE [object_id] = OBJECT_ID(@TableName)
) AS c
WHERE c.RowNumber != 1 -- not first column
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, LEN(@Delimiter) + 7, '') + ')
FROM ' + @TableName + ';';
EXECUTE sp_executesql @SQL;
您需要为此使用动态SQL: 警告: 我使用了tempdb(
tempdb.sys.columns
),因为我无法在演示中创建普通表。在您的情况下,请使用普通数据库。并将条件更改为:其中object\u id=object\u id('table\u name')
使用动态SQL,记住要考虑空值
declare @sql nvarchar(max), @t sysname, @c sysname
select @sql = 'select ', @t = '[dbo].[CONTACTS]' /* <---- YOUR TABLE NAME HERE */
declare cols cursor for
select name from sys.columns where object_id = object_id(@t) order by column_id
open cols
fetch next from cols INTO @c
while @@FETCH_STATUS = 0
begin
select @sql = @sql + 'convert(nvarchar(max), isnull(' + @c + ', '''')) + '
fetch next from cols INTO @c
end
close cols
deallocate cols
select @sql = left(@sql, len(@sql)-2) + ' from ' + @t
exec sp_executesql @sql
声明@sql nvarchar(max)、@t sysname、@c sysname
选择@sql='select',@t='[dbo].[CONTACTS]'/*如果您的表有一个主键列,您可以使用如下示例所示的相关子查询
没有列名不可能我可以建议一个更好的表名吗?在名称中的表名中包含类似于schema的内容不是很好的实践,在名称中包含表也不是。表名中有句号只是自找麻烦谢谢你,小伙子!这正是我需要的。:)不幸的是,我无法计算我必须更改什么才能使它在我的数据库中工作。@JimBoy将tempdb.sys.columns
更改为sys.columns
,其中object\u id=object\u id('table\u name')
和选项卡更改为您的\u table\u name
。就这些;)谢谢你的帮助!根据您的解释,我更改了所有内容,但没有显示结果表。@JimBoy和类似“C%”的名称。
您有类似C..或的列吗?
?如果是“更改<代码>”和“C%%”/代码>到“代码>”,名称类似“购买%”/代码> N.B.实际函数<代码> QualAdMe()/代码>比链接括号更安全,请考虑下表->代码>创建表βt(“愚蠢[]名称”VARCHAR(5));--使用quotename将正确转义为:[dumby[]]Name]
,而仅仅串联括号将给出[dumby[]Name]
,从而导致语法错误。虽然我承认这是一个令人憎恶的对象名称,但有时人们需要迎合这一点。谢谢你加雷斯!您的代码在我的SQL Server实例上运行时没有任何错误消息,但我没有得到显示的结果。您知道这是为什么吗?您是否已将@TableName
的值从'dbo.YourTable'
更新为实际的表名?非常感谢!)有没有办法在不同的字符串之间放置分隔符?很好!但现在我看到NULL
也被计算在内。有没有一种简单的方法可以抑制这种情绪?非常感谢您的详细解释!:)最后一个问题:我可以从进程中排除表的第一列吗?
(SELECT ',' + CONCAT(QUOTENAME(name) , ','' ''' )
declare @sql nvarchar(max), @t sysname, @c sysname
select @sql = 'select ', @t = '[dbo].[CONTACTS]' /* <---- YOUR TABLE NAME HERE */
declare cols cursor for
select name from sys.columns where object_id = object_id(@t) order by column_id
open cols
fetch next from cols INTO @c
while @@FETCH_STATUS = 0
begin
select @sql = @sql + 'convert(nvarchar(max), isnull(' + @c + ', '''')) + '
fetch next from cols INTO @c
end
close cols
deallocate cols
select @sql = left(@sql, len(@sql)-2) + ' from ' + @t
exec sp_executesql @sql
SELECT (
( SELECT *
FROM dbo.table1 AS t2
WHERE t2.C1 = t1.C1 --specify primary key column(s) here
FOR
XML PATH('test')
, TYPE
)).value('/test[1]', 'nvarchar(MAX)') AS ConcatenatedValue
FROM dbo.table1 AS t1;