SQL在不知道列的情况下将行选择为字符串变量

时间:2010-02-24 19:11:28

标签: sql sql-server tsql string dynamic

我是编写SQL的新手,非常感谢这个问题的帮助。 :)

我正在尝试将整行选择为字符串,最好用空格或逗号分隔。我想以通用的方式完成此任务,而无需了解表中列的具体信息。

我喜欢做的是:

DECLARE @MyStringVar NVARCHAR(MAX) = ''
@MyStringVar = SELECT * FROM MyTable WHERE ID = @ID AS STRING

但我最终做的是:

DECLARE @MyStringVar = ''
DECLARE @SecificField1 INT
DECLARE @SpecificField2 NVARCHAR(255)
DECLARE @SpecificField3 NVARCHAR(1000)
...
SELECT @SpecificField1 = Field1, @SpecificField2 = Field2, @SpecificField3 = Field3 FROM MyTable WHERE ID = @ID
SELECT @StringBuilder = @StringBuilder + CONVERT(nvarchar(10), @Field1) + ' ' +  @Field2 + ' ' + @Field3

呸。 :(

我看到有些人发布了有关COALESCE功能的内容,但是我再次没有看到有人在没有特定列名的情况下使用它。

另外,我在想,也许有一种方法可以使用列名来动态获取它们:

SELECT [COLUMN_NAME] FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'MyTable' 

看起来真的不应该这么复杂。 :(

我现在所做的工作,但提前感谢任何能指出我更好解决方案的人。 :)

编辑: 得到了解决,感谢所有回答的人。 :)

5 个答案:

答案 0 :(得分:3)

尝试一下:

DECLARE @SQL nvarchar(MAX), @YourTable nvarchar(200)
SET @YourTable='YourTableName'
SELECT @SQL=
    STUFF(
             (
                  SELECT
                  ' + '','' + COALESCE(''''''''+CONVERT(NVARCHAR(MAX),['+c.COLUMN_NAME+']'+CASE WHEN c.DATA_TYPE='datetime' THEN ',121' ELSE '' END+')+'''''''',''null'')'
                      FROM INFORMATION_SCHEMA.COLUMNS c
                      WHERE c.TABLE_NAME = 'ap_voucher'
                      ORDER BY ORDINAL_POSITION
                      FOR XML PATH('')
             ), 1, 9, ''
         )
SET @SQL = 'SELECT ' + @SQL + ' FROM '+@YourTable
exec (@SQL)

示例输出:

---------------------------------------------------------------------------
'030',null,'I','Zzz0',null,'1000021111          ','2000-03-01 00:00:00.000'
'001',null,'I','zzz0',null,'900099618           ','1999-12-03 00:00:00.000'
'001',null,'I','ET10',null,'KOU557              ','1999-11-01 00:00:00.000'
'001',null,'I','Mzzz',null,'017288              ','1999-11-12 00:00:00.000'

答案 1 :(得分:1)

要动态地做,只要知道表名,就可以使用这种方法:

DECLARE @nSQL NVARCHAR(MAX)
SELECT @nSQL = COALESCE(
     @nSQL + ' + '','' + CAST(ISNULL([' + c.COLUMN_NAME + '], '''') AS NVARCHAR(MAX))', 
    'CAST([' + c.COLUMN_NAME + '] AS NVARCHAR(MAX))')
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME = 'TestTable'

SET @nSQL = 'SELECT ' + @nSQL + ' FROM YourTable'

EXECUTE sp_executesql @nSQL

这取决于你的最终目标。

这将处理列中的空值,但是(例如)NULL整数例如为0。

答案 2 :(得分:0)

简短的回答是你做不到。

你唯一可以做的就是拥有你所拥有的东西。

SELECT @MyField1 = MyField1, @MyField2= MyField2...etc FROM MyTable

然后你可以连接这些字段:

SELECT @MyResult = (SELECT @MyField1 + @MyField2 + MyField3...)

SELECT @MyResult

答案 3 :(得分:0)

如果您可以处理XML格式的输出,那么这样的事情可能会起作用:

DECLARE @MyStringVar NVARCHAR(MAX) = ''
SET @MyStringVar = (SELECT * FROM MyTable WHERE ID = @ID FOR XML RAW)

SELECT @MyStringVar 

作为额外奖励,如果您的数据适合它,您可以使用此格式删除XML格式,而不是SELECT @MyStringVar

SELECT REPLACE(REPLACE(REPLACE(REPLACE(@MyStringVar, '<row ', ''), '="', ' '), '" ', ', '), '"/>', '')

如果你的数据包含在标签中使用的任何字符,当然你必须做一些额外的转换,但这应该让你非常接近你想要的。


注意到您实际上并不希望显示列名和数据。在这种情况下,其他答案中的information_schema查询之一将是获得所需内容的最佳方式。

答案 4 :(得分:0)

如果目标是更改跟踪,那么我建议不要使用KM建议的连接。

  1. 列的顺序必须保持不变。如果列顺序稍有变化,则值的含义最多或者更有可能丢失。建议您永远不要依赖列顺序。

  2. 随着表格变宽和/或包含大量数据,连接将变得更慢。 SQL Server不知道是否具有高效的连接。进一步,想象一个包含几十个nvarchar(max)字段的表,每个字段有2000个字符。这将产生一个大约48K的字符串!

  3. 您可能需要更改分隔符。假设我的值等于“'痛苦','苦难'和'麻烦'”。当您去分析数据时,这种类型的条目会产生问题。

  4. 如果您使用的是SQL Server 2008,我建议您使用SQL Server的更改跟踪机制。如果您不使用它,那么我建议您购买第三方审核工具。如果这也不是一个选项,那么我会使用触发器将删除的值写入另一个表。这至少会迫使您确保审计数据模式与源模式同步。