我正在编写一个存储过程来为管理员创建一组DELETE
语句来对数据库运行
作为“回滚”解决方案的一部分,我希望,对于我要删除的每一行,还要单独创建相应的INSERT
语句,以便运行脚本的人希望撤消,他们可以简单地对数据库运行insert语句
我的问题是,如果我有一个表有8列(Col1..Col8)的表,我如何在所有列的逗号分隔列表中提取值,以便我最终得到
INSERT INTO Table VALUES (Col1value, Col2value, ...Col8value)
答案 0 :(得分:6)
请考虑以下命令:
SELECT 'SELECT ' +
STUFF ((
SELECT ', [' + name + ']'
FROM syscolumns
WHERE id = OBJECT_ID('Table') AND
name <> 'me'
FOR XML PATH('')), 1, 1, '') +
' FROM [Table]'
这将为特定表构建SELECT
语句。要构建INSERT
语句,它可能如下所示:
SELECT @sql = 'INSERT INTO [Table] (' +
STUFF ((
SELECT ', [' + name + ']'
FROM syscolumns
WHERE id = OBJECT_ID('Table') AND
name <> 'me'
FOR XML PATH('')), 1, 1, '') +
') VALUES (' +
STUFF ((
SELECT ', @' + name
FROM syscolumns
WHERE id = OBJECT_ID('Table') AND
name <> 'me'
FOR XML PATH('')), 1, 1, '') + ')'
当然有很多方法可以找到INSERT
声明,根据自己的喜好来制作它。
答案 1 :(得分:2)
在等待其他专家的通用解决方案时,如果表结构已知并且稳定,这是一个适当的权宜版本。这个测试数据: -
create table #mytable (
col1value varchar (50),
col2value int,
col3value decimal(10, 5),
col4value date,
col5value datetime
);
insert into #mytable values
(null,1,234.567,'2013-12-20','2013-01-07T17:30:24.567'),
('def',null,987.645,'2013-12-21','2013-01-01'),
('abc',17,null,'2013-12-20','2013-10-07T11:31:21.517'),
('jkl',2,3232.32,null,'2013-01-01 01:02:03.456'),
('mno',2,7.4006,'2012-07-04',null)
允许此代码: -
select 'insert into #myTable values (' +
isnull('''' + col1value + '''','null') + ',' +
isnull(convert(varchar(50),col2value),'null') + ',' +
isnull(convert(varchar(50),col3value),'null') + ',' +
isnull('''' + convert(varchar(50),col4value) + '''','null') + ',' +
isnull('''' + convert(varchar(50),col5value,121) + '''','null') +
')'
from #mytable
制作: -
insert into #myTable values (null,1,234.56700,'2013-12-20','2013-01-07 17:30:24.567')
insert into #myTable values ('def',null,987.64500,'2013-12-21','2013-01-01 00:00:00.000')
insert into #myTable values ('abc',17,null,'2013-12-20','2013-10-07 11:31:21.517')
insert into #myTable values ('jkl',2,3232.32000,null,'2013-01-01 01:02:03.457')
insert into #myTable values ('mno',2,7.40060,'2012-07-04',null)
您可以通过在insert
语句中包含列列表来防止结构更改(在某种程度上)。即使有列列表 - 如果有人在没有默认值的情况下向表中添加了一个不可为空的列 - 您的插入将失败(除非您在更改架构时按下它们)。
我总是会使用代码工厂来生成这种代码(即在信息模式上运行的SP - 使用列类型来构建代码以序列化每种类型的值)。
上面的示例仅处理您可能需要处理的一些类型 - 但您应该能够找出如何处理所有其他类型。
答案 2 :(得分:0)
您可以创建一个临时表,然后在您的过程中插入一行,将该行添加到您的temprory表中。 当此人想撤消时只需获取表格的最后一行(插入时添加一个带有时间或日期的额外列)并在主表中插入此行。
希望这有帮助。
答案 3 :(得分:0)
如果您使用第三方工具,则可以使用SSMS Tools Pack
它是版本2005,2008,2008 R2和2012的Microsoft SQL Server Management Studio(SSMS)加载项。
它可以做很多事情,包括:为表,视图或整个数据库生成插入语句(参见功能页面:Insert statement generator)。
我自己用它做你要问的同样的事情:为大量数据记录创建一个备份,这样我们就可以轻松地回滚我们的更改。
答案 4 :(得分:0)
这将起作用..传递表名,要应用条件的列名并传递条件。喜欢exec sp_get_columns 'tbl_name', 'column_name', '100'
CREATE or ALTER PROCEDURE SP_GET_COLUMNS
@TABLE_NAME varchar(256)
,@COND_COL varchar(256)
,@COND varchar(256)
AS
BEGIN
SELECT IDENTITY(int, 1, 1) seq_no, COLUMN_NAME into #temp FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TABLE_NAME
Declare @Data AS Nvarchar(MAX)
SELECT @Data = COALESCE(@Data + ','','',', '') + COLUMN_NAME FROM #temp
DECLARE @query varchar(1000) = 'SELECT CONCAT(' + @Data + ') from ' + @TABLE_NAME + ' where ' + @COND_COL + ' = ''' + @COND + ''''
CREATE TABLE #temp2 (val VARCHAR(8000))
INSERT INTO #temp2 exec(@query)
SELECT REPLACE(REPLACE(CONCAT('INSERT INTO ',@TABLE_NAME,' VALUES(''', REPLACE(val,',',''',''') ,''')'),',''''',',NULL'),','''',',',NULL,') as Query FROM #temp2
drop Table #temp,#temp2
END