代码之家  ›  专栏  ›  技术社区  ›  Brandi

SQL select row转换为字符串变量而不知道列

  •  3
  • Brandi  · 技术社区  · 16 年前

    我试图将整行选择为一个字符串,最好用空格或逗号分隔。我想用一种通用的方式来完成这一点,而不必知道关于表中列的细节。

    我想做的是:

    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 回复  |  直到 16 年前
        1
  •  3
  •   KM.    16 年前

    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'
    
        2
  •  1
  •   AdaTheDev    16 年前

    要动态执行此操作,只需知道表名,就可以使用以下方法:

    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
    

    但这取决于你的最终目标是什么。

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

        3
  •  0
  •   JonH    16 年前

    简而言之,你不能那样做。

    你唯一能做的就是与你所拥有的相似。

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

    SELECT @MyResult = (SELECT @MyField1 + @MyField2 + MyField3...)
    
    SELECT @MyResult
    
        4
  •  0
  •   mwigdahl    16 年前

    如果您可以处理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 ', ''), '="', ' '), '" ', ', '), '"/>', '')
    

    如果您的数据包含标签中使用的任何字符,那么您当然需要进行一些额外的转换,但这将使您非常接近您想要的。


    只是注意到看起来您实际上并不希望列名和数据一起显示。在这种情况下,其他答案中的一个信息模式查询将是获得所需信息的最佳方式。

        5
  •  0
  •   Thomas    16 年前

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

    1. 列的顺序必须保持不变。如果列顺序稍微改变,值的含义充其量就是模糊的,或者更可能是丢失的。建议不要依赖列顺序。

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