这可能是一个有限但有价值的场景。我有一个SQL Server 2008数据库,其中包含一个包含数百万条记录的表。一些记录似乎存在间歇性问题。我试图重复这个问题。为了做到这一点,我终于得到了一个违规记录的ID。我想在PROD数据库中生成与此单个记录关联的INSERT语句。然后我可以轻松地将其迁移到我的TESTING数据库中,以便重现并解决问题。
基本上,我需要为单个表生成单个INSERT语句,我知道记录的主键值。
有没有人对如何做到这一点有任何想法?基本上,我想在条件基础上生成插入语句。
谢谢!
答案 0 :(得分:5)
首先尝试使用SELECT
语句重新创建要插入的内容。
之后,您可以使用INSERT INTO
这样插入表中:
INSERT INTO tablename
SELECT ....
如果它们位于不同的服务器上,您可以像这样使用INSERT:
INSERT INTO tablename VALUES (...)
使用其他服务器中SELECT
给出的值填充插入中的值。
答案 1 :(得分: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个警告,我还没有测试过所有数据类型等等。
然而,在更一般的情况下,有一个 lot 比这更多。 Vyas K有一个非常强大的存储过程,应该证明它可以获得多么复杂:
http://vyaskn.tripod.com/code/generate_inserts_2005.txt
使用像Red-Gate's SQL Data Compare这样的工具挑选特定行并为您生成插入内容可能会好得多。 As I've blogged about,为工具付费不仅仅是关于钱,而是关于其他人已经为你做过的故障排除和错误修复的时间。
答案 2 :(得分:2)
亚伦 我喜欢你的代码,它为我解决了一个问题。我遇到了一些使用它的问题(就像你说的那样),使用空值和文本类型,所以我做了一些更改来解决这些问题。
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