Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何在SQL查询中通过标识将具有不同类型的表的所有列的值连接起来?_Sql Server - Fatal编程技术网

Sql server 如何在SQL查询中通过标识将具有不同类型的表的所有列的值连接起来?

Sql server 如何在SQL查询中通过标识将具有不同类型的表的所有列的值连接起来?,sql-server,Sql Server,我希望有一个函数来获取表名和行ID并返回nvarchar类型,例如,我有一个如下所示的表a: TABLE A ( ID INT IDENTITY, Name NVARCHAR(50) NOT NULL, Active BIT NULL, Date DATE NULL ) 例如,第一行值为: 1,'jon',true,'06/08/2018' 此函数应返回以下输出: ID:'1', Name:'jon', Active:'true', Date:'06/08/

我希望有一个函数来获取表名和行ID并返回nvarchar类型,例如,我有一个如下所示的表a:

TABLE A 
(
    ID INT IDENTITY,
    Name NVARCHAR(50) NOT NULL,
    Active BIT NULL,
    Date DATE NULL
)
例如,第一行值为:

1,'jon',true,'06/08/2018'
此函数应返回以下输出:

ID:'1', Name:'jon', Active:'true', Date:'06/08/2018'
更多说明:
我有一个日志表,当从任何其他表中删除一行时,我希望将所有列及其值作为文本复制到日志表中,如上所述。

因为这些事情应该在前端或应用程序层中完成,所以我建议对此使用一个内联表值函数。注意不要使用标量函数,因为它的性能并不好

CREATE FUNCTION dbo.itvf_concata (
                                       @id INT
                                 )
RETURNS TABLE
RETURN SELECT 'ID:''''' + CONVERT(VARCHAR(12), id) 
              + ''''', Name:''''' + name 
              + ''''', Active:'''''
              + CASE
                      WHEN Active = 1 THEN 'TRUE' 
                      ELSE    'FALSE' 
                END 
              + ''''', Date:''''' + CONVERT(VARCHAR(10), [Date],101) + ''''
       FROM   a
       WHERE  id = @id;
正如在comment中讨论的,UDF不起作用,因为下面的查询处理的是动态SQL。虽然我不推荐长期使用此解决方案,因为它涉及很多动态查询

代码是不言自明的。首先获取转换为NVARCHAR的列和列列表。然后获取数据取消激活列名和值。然后根据需要连接结果

创建这样一个过程

CREATE PROC uspGetLogString(@TABLE VARCHAR(50), @ID INT)
AS
    BEGIN
    DECLARE @RETURNVALUE NVARCHAR(MAX) = ''
    DECLARE @WHERECLAUSE NVARCHAR(MAX) = 'ID = ' + CONVERT(NVARCHAR(50), @ID)
    DECLARE @COLUMNSWITHTYPE NVARCHAR(MAX) = ''
    DECLARE @COLUMNS NVARCHAR(MAX) = ''

    SELECT @COLUMNSWITHTYPE  = @COLUMNSWITHTYPE + 
        CASE 
            WHEN CL.DATA_TYPE = 'BIT' THEN 'CONVERT(NVARCHAR(50), CASE WHEN ' + CL.COLUMN_NAME + ' = 1 THEN ''True'' ELSE ''False'' END) AS ' + CL.COLUMN_NAME + ''
            WHEN CL.DATA_TYPE != 'NVARCHAR' THEN 'CONVERT(NVARCHAR(50), ' + CL.COLUMN_NAME + ') AS ' + CL.COLUMN_NAME + '' 
            ELSE CL.COLUMN_NAME 
        END  + ', ' FROM INFORMATION_SCHEMA.COLUMNS CL WHERE TABLE_NAME = @TABLE
    SELECT @COLUMNS  = @COLUMNS + CL.COLUMN_NAME + ', ' FROM INFORMATION_SCHEMA.COLUMNS CL WHERE TABLE_NAME = @TABLE

    SELECT @COLUMNSWITHTYPE = LEFT(@COLUMNSWITHTYPE, LEN(@COLUMNSWITHTYPE) - 1)
    SELECT @COLUMNS = LEFT(@COLUMNS, LEN(@COLUMNS) - 1)
    SELECT @COLUMNSWITHTYPE = 'SELECT ' + @COLUMNSWITHTYPE + ' FROM ' + @TABLE + ' WHERE ' + @WHERECLAUSE

    DECLARE @DynamicSQL NVARCHAR(MAX) = ''

    SELECT @DynamicSQL = 'DECLARE @RESULT NVARCHAR(MAX) = ''''
    SELECT @RESULT = @RESULT + TAB.COLUMN_NAME + '':'' + U.ColumnValue +'', ''
    FROM INFORMATION_SCHEMA.COLUMNS TAB
    INNER JOIN
        (
            SELECT ColumnName, ColumnValue
            FROM (' +  @COLUMNSWITHTYPE + ')
            AS P
            UNPIVOT
            (
                ColumnValue FOR ColumnName IN (' + @COLUMNS + ' )
            ) as unpvt 
        )
         as U ON U.ColumnName = Tab.COLUMN_NAME
    WHERE TAB.TABLE_NAME = ''' +  @TABLE + ''';
    SELECT @RESULT = LEFT(@RESULT, LEN(@RESULT) - 1)
    SELECT @RESULT
    '
    EXEC SP_EXECUTESQL @DynamicSQL, N'@OUTPUT NVARCHAR(MAX) OUT', @RETURNVALUE
END
GO
那就这样说吧

EXEC dbo.uspGetLogString 'EMPLOYEE', 1
我更改了@Selva TS答案以更正错误,最后得出以下结论:

CREATE PROC dbo.SP_GetLogString (@TABLE VARCHAR(50), @ID INT)
AS
BEGIN
DECLARE @RETURNVALUE NVARCHAR(MAX) = ''
DECLARE @PKey NVARCHAR(50) = (SELECT
  column_name AS PRIMARYKEYCOLUMN
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU
  ON TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
  AND TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
  AND KU.table_name = @TABLE)
DECLARE @WHERECLAUSE NVARCHAR(MAX) = @PKey + ' = ' + CONVERT(NVARCHAR(50), 1000)
DECLARE @COLUMNSWITHTYPE NVARCHAR(MAX) = ''
DECLARE @COLUMNS NVARCHAR(MAX) = ''

SELECT
@COLUMNSWITHTYPE = @COLUMNSWITHTYPE +
CASE
  WHEN CL.DATA_TYPE = 'BIT' THEN 'CONVERT(NVARCHAR(max), CASE WHEN ' +            CL.COLUMN_NAME + ' = 1 THEN ''True'' ELSE ''False'' END) AS ' + CL.COLUMN_NAME + ''
  WHEN CL.DATA_TYPE = 'float' THEN 'CONVERT(NVARCHAR(max), CONVERT(numeric,' + CL.COLUMN_NAME + ')) AS ' + CL.COLUMN_NAME + ''
  ELSE 'CONVERT(NVARCHAR(max), ' + CL.COLUMN_NAME + ') AS ' + CL.COLUMN_NAME + ''
END + ', '
FROM INFORMATION_SCHEMA.COLUMNS CL
WHERE TABLE_NAME = @TABLE
AND CL.DATA_TYPE <> 'image'
SELECT
@COLUMNS = @COLUMNS + CL.COLUMN_NAME + ', '
FROM INFORMATION_SCHEMA.COLUMNS CL
WHERE TABLE_NAME = @TABLE
AND CL.DATA_TYPE <> 'image'

SELECT
 @COLUMNSWITHTYPE = LEFT(@COLUMNSWITHTYPE, LEN(@COLUMNSWITHTYPE) - 1)
SELECT
@COLUMNS = LEFT(@COLUMNS, LEN(@COLUMNS) - 1)
SELECT
@COLUMNSWITHTYPE = 'SELECT ' + @COLUMNSWITHTYPE + ' FROM ' + @TABLE + ' WHERE ' +   @WHERECLAUSE

DECLARE @DynamicSQL NVARCHAR(MAX) = ''

SELECT
@DynamicSQL = 'DECLARE @RESULT NVARCHAR(MAX) = ''''
SELECT @RESULT = @RESULT + TAB.COLUMN_NAME + '':'' + U.ColumnValue +'', ''
FROM INFORMATION_SCHEMA.COLUMNS TAB
INNER JOIN
    (
        SELECT ColumnName, ColumnValue
        FROM (' + @COLUMNSWITHTYPE + ')
        AS P
        UNPIVOT
        (
            ColumnValue FOR ColumnName IN (' + @COLUMNS + ' )
        ) as unpvt 
    )
     as U ON U.ColumnName = Tab.COLUMN_NAME
 WHERE TAB.TABLE_NAME = ''' + @TABLE + ''' and TAB.DATA_TYPE<>''image'';
 SELECT @RESULT = LEFT(@RESULT, LEN(@RESULT) - 1)
   SELECT @RESULT'  EXEC SP_EXECUTESQL @DynamicSQL  ,N'@OUTPUT NVARCHAR(MAX)OUT',@RETURNVALUE
END
GO

你能再解释一下吗?我想选择一个指定的按id的行,将所有列名及其值作为文本连接在一起,就像我上面提到的。这种连接应该在查询中完成吗?是的,正如我所说,我想在函数中使用它。你需要定义转义规则:如果名称包含撇号,你想要什么,约翰·奥谢?那桌子名呢?我想要它作为参数。当Table Name为parameter时,列名也会更改。@doomiyar,您想用常规查询来查询所有以Table Name为参数的表吗?我编写的函数只查询您提到的作为AOk的表,但是在第一行,我提到我想要一个函数来获取Tabel Name和row ID,并在您提到的返回语句中返回一个nvarchar类型,例如ID:'1',Name:'jon',Active:'true',Date:'06/08/2018',并且没有表名here@SwlvaTS,谢谢,但当标识列未命名为ID时出现错误,还有其他错误,比如:列的类型与UNPIVOT列表中指定的其他列的类型冲突。最后,我通过动态查找主键并进行一些更改来纠正错误。再次感谢你的帮助。