1

私はこれをしばらく検索しましたが、私がやろうとしていることに対する「特効薬」の解決策があるかどうかはわかりません。DB にテーブルがあります (この議論のために、実際の列は関係ありません)。同じテーブルから 2 つの行を見て、2 つの間で異なる列のリストを取得できるようにしたいと考えています。

特定のテーブルに対してこれを実現するために大量の TSQL を記述できることはわかっていますが、これを実行できる SQL Server (2008 R2 を実行しています) に組み込み関数があることを望んでいました。

2 つの行が異なるかどうかを教えてくれる CHECKSUM のような単純な関数があることは知っていますが、どの列が異なるかの詳細が必要です。

できれば、それをUDFにして、テーブル名と、比較したい2行の主キーを渡したいと思います。

何か考えや提案はありますか?

--編集--これが私が思いついた解決策です:

Well, It is certainly not the most elegant solution...but it will work in a pinch.

    CREATE PROCEDURE sp_Compare_Table_Rows
    (
        @TablePK varchar(1000), -- The Name of the Primary Key in that Table
        @TableName varchar(1000), -- The Name of the Table
        @PK1 int, -- The ID of the 1st table
        @PK2 int -- The ID of the 2nd table
    )
    AS
    DECLARE @Holder table
    (
        Column_Name varchar(250),
        Different bit
    )
    INSERT INTO @Holder(Column_Name,Different)
    select 
    COLUMN_NAME,0
    from 
    LPS_DEV.INFORMATION_SCHEMA.COLUMNS
    WHERE
    TABLE_NAME = @TableName
    and ORDINAL_POSITION >1

    DECLARE @LoopedColumnName varchar(250)
    DECLARE @DynamicQuery nvarchar(max)
    DECLARE @ORD1 int
    DECLARE @ORD2 int

    SET @DynamicQuery = ''
    SET @LoopedColumnName = ''
    SET @ORD1 = 0
    SET @ORD2 = 0

    DECLARE MYCUR CURSOR FOR SELECT Column_Name FROM @Holder
    OPEN MYCUR
    FETCH NEXT FROM MYCUR INTO @LoopedColumnName
    WHILE @@FETCH_STATUS = 0
        BEGIN
            SET @DynamicQuery = 'SELECT @Outer= CHECKSUM(' + @LoopedColumnName + ') FROM ' + @TableName + ' WHERE ' + @TablePK + ' = ' + CONVERT(varchar(100),@PK1)
            exec sp_executesql @DynamicQuery, N'@Outer int output',@ORD1 out

            SET @DynamicQuery = 'SELECT @Outer= CHECKSUM(' + @LoopedColumnName + ') FROM ' + @TableName + ' WHERE ' + @TablePK + ' = ' + CONVERT(varchar(100),@PK2)
            exec sp_executesql @DynamicQuery, N'@Outer int output',@ORD2 out

            IF @ORD1 <> @ORD2 
            BEGIN
                UPDATE @Holder SET Different = 1 WHERE Column_Name = @LoopedColumnName
            END     
            FETCH NEXT FROM MYCUR INTO @LoopedColumnName    
        END
    CLOSE MYCUR
    DEALLOCATE MYCUR

    select * from @Holder
4

3 に答える 3

0

ジョン、あなたはこのようなものを使うことができます。これにより、列名が表示されます - @tablename と @whereclause を設定します。

declare @tablename varchar(1000), 
@cols varchar(max), 
@sqlstmt nvarchar(max),
@whereclause nvarchar(max);
    set @tablename = 'sometable';
    set @whereclause = ' where
        a.col1 = ''SOMEOTHERVALUE'' and a.datecol2 = ''19910101'' and
        b.col2 = ''SOMEVALUE'' and b.datecol2 = ''19910101''
    '
    select @cols = stuff((
        select ', case when a.' + c.name + ' = b.' + c.name 
           + ' then '''' else ''' + c.name + ''' end'
            from sys.columns c
            inner join sys.tables t on c.object_id = t.object_id
            where t.name = @tablename
            for xml path ('')), 1, 1, '')

    set @sqlstmt = 'select ' + @cols + ' from ' + @tablename 
                  + ' a, ' + @tablename + ' b ' + @whereclause
    exec sp_executesql @sqlstmt
于 2013-09-26T18:01:33.747 に答える
0

私はSriramの回答にいくつかの機能強化を行いました.これが新しいスクリプトです:

declare @tablename nvarchar(MAX), 
@cols varchar(max) = '', 
@sqlstmt nvarchar(max) = 'DECLARE @T AS TABLE (ColumnName NVARCHAR(MAX), Value NVARCHAR(MAX), Value2 NVARCHAR(MAX))',
@whereclause nvarchar(max) = '';

set @tablename = 'TABLE_NAME';
set @whereclause = ' where a.FIRST_ROW_ID = ''NUMBER'' and b.SECOND_ROW_ID = ''NUMBER'''

select @cols = (
    select ' INSERT INTO @T SELECT ''' + c.name + ''', cast(a.' + c.name + ' as nvarchar(max)), cast(b.' + c.name + ' as nvarchar(max)) from ' + @tablename + ' a, ' + @tablename + ' b ' + @whereclause + ' AND  cast(a.' + c.name + ' as nvarchar(max)) != cast(b.' + c.name + ' as nvarchar(max))'
            from sys.columns c
            inner join sys.tables t on c.object_id = t.object_id
            where t.name = @tablename
            for xml path (''))

set @sqlstmt += @cols + ' SELECT * FROM @T'

exec sp_executesql @sqlstmt

「TABLE_NAME」をテーブルに置き換え、where 句の変数を変更する必要があります。

結果は次のようになります。

ColumnName | Value  | Value2
----------------------------
Id         | 1      | 2 
Name       | Name 1 | Name 2
于 2017-08-23T12:51:31.310 に答える