2012-05-17 43 views
6

Đây có thể là một chút về một kịch bản hạn chế, nhưng có giá trị. Tôi có một cơ sở dữ liệu SQL Server 2008 với một bảng có hàng triệu bản ghi. Dường như có một vấn đề liên tục với một số hồ sơ. Tôi đang cố gắng để repro vấn đề. Trong một nỗ lực để làm điều này, cuối cùng tôi đã nhận được ID của một hồ sơ vi phạm. Tôi muốn tạo một câu lệnh INSERT được liên kết với bản ghi đơn này trong cơ sở dữ liệu PROD của tôi. Sau đó, tôi có thể dễ dàng di chuyển nó vào cơ sở dữ liệu TESTING của tôi trong một nỗ lực để repro và giải quyết vấn đề.Tạo các tập lệnh cho các bản ghi cụ thể trong SQL Server

Về cơ bản, tôi cần tạo một câu lệnh INSERT duy nhất cho một bản ghi từ một bảng duy nhất mà tôi biết giá trị khóa chính của bản ghi.

Có ai có ý tưởng nào về cách tôi có thể thực hiện việc này không? Về cơ bản, tôi muốn tạo các câu lệnh chèn trên cơ sở có điều kiện.

Cảm ơn bạn!

+1

lược đồ bảng? điều kiện? có những người khá thông minh ở đây nhưng không ai trong số họ là tiên tri: P –

+0

Tôi vừa cập nhật câu hỏi. Cảm ơn. – user70192

Trả lời

4

Trước tiên, hãy thử tạo lại những gì bạn muốn chèn bằng tuyên bố SELECT.

Sau đó bạn có thể chèn vào bảng với một INSERT INTO như thế này:

INSERT INTO tablename 
SELECT .... 

Nếu họ đang ở trên máy chủ khác nhau, bạn có thể sử dụng INSERT như thế này:

INSERT INTO tablename VALUES (...) 

sử dụng các giá trị được đưa ra bởi các SELECT trong máy chủ khác điền vào các giá trị trong chèn.

+0

Nếu đây là trên các máy chủ khác nhau, điều này sẽ yêu cầu máy chủ được liên kết.Tôi thích ý tưởng này tốt hơn nhưng tôi nghĩ rằng OP đang cố gắng tạo ra một chuỗi tĩnh với các giá trị để sao chép, dán và thực hiện ở nơi khác. –

+0

@AaronBertrand đúng như vậy! Tôi đã chỉnh sửa để thêm thông tin đó. –

+0

Tuyệt vời Sir! câu trả lời rất có giá trị. –

5

Trong trường hợp cụ thể của bạn tôi nghĩ bạn có thể làm điều này:

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 

Vì vậy, hãy thử nó ra:

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' 

Nếu có một cột IDENTITY bạn có thể cần phải thiết lập SET IDENTITY_INSERT ON cho bảng TEST và xác minh rằng không có xung đột. Có lẽ khoảng 500 cảnh báo tôi nên đề cập đến, tôi chưa thử nghiệm tất cả các loại dữ liệu, v.v.

Tuy nhiên, trong trường hợp tổng quát hơn, có nhiều hơn thế. Vyas K có một thủ tục lưu trữ khá mạnh mẽ mà phải chứng minh như thế nào phức tạp nó có thể nhận được:

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

Bạn đang có lẽ tốt hơn bằng cách sử dụng một công cụ như Red-Gate's SQL Data Compare để chọn một hàng cụ thể và tạo ra một chèn cho bạn. As I've blogged about, trả tiền cho một công cụ không chỉ là về số tiền, mà còn về số giờ khắc phục sự cố và sửa lỗi mà người khác đã thực hiện cho bạn.

+0

Tôi cần thực hiện một số thay đổi đối với mã bạn đã viết ở trên (nhờ btw). Nó đã được lớn cho một bình luận và tôi đã không chắc chắn các nghi thức về chỉnh sửa mã trong bài viết của bạn vì vậy tôi thêm nó dưới đây. – RobRolls

2

Aaron, Tôi thích mã của bạn, nó đã giải quyết được sự cố cho tôi. Tôi chạy vào một vài vấn đề bằng cách sử dụng nó (như bạn đã nói tôi sẽ) với null và loại văn bản vì vậy tôi đã thực hiện một số thay đổi để giải quyết những vấn đề đó.

ALTER 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 + ' + '','' + ' + 'ISNULL('+REPLICATE(CHAR(39),4)+'+RTRIM(' + 
             CASE WHEN system_type_id IN (40,41,42,43,58,61) -- datetime types 
             THEN 
              'CONVERT(CHAR(8), ' + QUOTENAME(name) + ', 112) + '' ''+ CONVERT(CHAR(14), ' + QUOTENAME(name) + ', 14)' 
             WHEN system_type_id IN (35) -- text type NOTE: can overflow 
             THEN 
              'REPLACE(CAST(' + QUOTENAME(name) + 'as nvarchar(MAX)),'+REPLICATE(CHAR(39),4)+','+REPLICATE(CHAR(39),6)+')' 
             ELSE 
              'REPLACE(' + QUOTENAME(name) + ','+REPLICATE(CHAR(39),4)+','+REPLICATE(CHAR(39),6)+')' 
             END 
           + ')+' + REPLICATE(CHAR(39),4) + ',''null'') + ' 

    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),2) + STUFF(@vals, 1, 6, '') + 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 
Các vấn đề liên quan