8

これはおそらく少し限定的ですが、価値のあるシナリオです。何百万ものレコードを持つテーブルを持つ SQL Server 2008 データベースがあります。いくつかのレコードに断続的な問題があるようです。問題を再現しようとしています。これを行うために、私は最終的に問題のあるレコードの ID を取得しました。PROD データベースのこの単一レコードに関連付けられた INSERT ステートメントを生成したいと考えています。次に、問題を再現して解決するために、それを TESTING データベースに簡単に移行できます。

基本的に、レコードの主キー値がわかっている単一のテーブルから、単一のレコードに対して単一の INSERT ステートメントを生成する必要があります。

どうすればこれを達成できるかについて誰かアイデアがありますか? 基本的に、条件に基づいて挿入ステートメントを生成したいと考えています。

ありがとうございました!

4

3 に答える 3

5

SELECTまず、ステートメントを使用して挿入するものを再作成してみてください。

INSERT INTOその後、次のようにテーブルに挿入できます。

INSERT INTO tablename
SELECT ....

それらが異なるサーバー上にある場合は、次のようにINSERTを使用できます。

INSERT INTO tablename VALUES (...)

他のサーバーで指定された値を使用してSELECT、挿入の値を入力します。

于 2012-05-17T13:13:12.970 に答える
5

あなたの特定のケースでは、これを行うことができると思います:

CREATE PROCEDURE dbo.GenerateSingleInsert
    @table     NVARCHAR(511), -- expects schema.table notation
    @pk_column SYSNAME,       -- column that is primary key
    @pk_value  INT            -- change data type accordingly
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @cols   NVARCHAR(MAX), @vals   NVARCHAR(MAX),
            @valOut NVARCHAR(MAX), @valSQL NVARCHAR(MAX);

    SELECT @cols = N'', @vals = N'';

    SELECT @cols = @cols + ',' + QUOTENAME(name),
           @vals = @vals + ' + ' + REPLICATE(CHAR(39),3) + ',' 
            + REPLICATE(CHAR(39),3) + ' + ' + REPLICATE(CHAR(39),2) + '+'
            + 'RTRIM(' + CASE WHEN system_type_id IN (40,41,42,43,58,61) THEN
             'CONVERT(CHAR(8), '  + QUOTENAME(name) + ', 112) + '' '' 
            + CONVERT(CHAR(14), ' + QUOTENAME(name) + ', 14)'
            ELSE 'REPLACE(' + QUOTENAME(name) + ','''''''','''''''''''')' END + ') 
            + ' + REPLICATE(CHAR(39),2)
      FROM sys.columns WHERE [object_id] = OBJECT_ID(@table)
      AND system_type_id <> 189 -- can't insert rowversion
      AND is_computed = 0;      -- can't insert computed columns

    SELECT @cols = STUFF(@cols, 1, 1, ''),
           @vals = REPLICATE(CHAR(39), 4) + ' + ' + STUFF(@vals, 1, 13, '') 
            + REPLICATE(CHAR(39), 2);

    SELECT @valSQL = N'SELECT @valOut = ' + @vals + ' FROM ' + @table + ' WHERE '
        + QUOTENAME(@pk_column) + ' = ''' + RTRIM(@pk_value) + ''';';

    EXEC sp_executesql @valSQL, N'@valOut NVARCHAR(MAX) OUTPUT', @valOut OUTPUT;

    SELECT SQL = 'INSERT ' + @table + '(' + @cols + ') SELECT ' + @valOut;
END
GO

それでは、試してみましょう:

CREATE TABLE dbo.splunge
(
    ID INT, dt DATETIME, rv ROWVERSION, t NVARCHAR(MAX)
);

INSERT dbo.splunge(ID, dt, t)
          SELECT 1, GETDATE(), 'foo'
    UNION ALL SELECT 2, GETDATE(), 'bar'
    UNION ALL SELECT 3, GETDATE(), 'O''Brien';

EXEC dbo.GenerateSingleInsert N'dbo.splunge', N'ID', 1;

SQL
-------------
INSERT dbo.splunge([ID],[dt],[t]) SELECT '1','20120517 10:07:07:330','foo'

EXEC dbo.GenerateSingleInsert N'dbo.splunge', N'ID', 2;

SQL
-------------
INSERT dbo.splunge([ID],[dt],[t]) SELECT '2','20120517 10:07:07:330','bar'

EXEC dbo.GenerateSingleInsert N'dbo.splunge', N'ID', 3;

SQL
-------------
INSERT dbo.splunge([ID],[dt],[t]) SELECT '3','20120517 10:07:07:330','O''Brien'

IDENTITY 列がある場合は、TEST テーブルに対して SET IDENTITY_INSERT ON を設定し、競合がないことを確認する必要がある場合があります。おそらく約 500 の注意事項があります。すべてのデータ型をテストしたわけではありません。

ただし、より一般的なケースでは、これよりも多くのことがあります。Vyas K には非常に堅牢なストアド プロシージャがあり、それがどれほど複雑になるかを示しています。

http://vyaskn.tripod.com/code/generate_inserts_2005.txt

Red-Gate の SQL Data Compare のようなツールを使用して特定の行を選択し、挿入を生成する方がおそらくはるかに優れています。についてブログで書いたように、ツールにお金を払うということは単にお金がかかるということではなく、他の誰かがあなたのために行ったトラブルシューティングやバグ修正に何時間も費やすということです。

于 2012-05-17T14:19:33.170 に答える