假设我想要合并两个用户(即需要删除用户。在此之前更新该用户与其他用户的所有引用)。 我想用新用户ID替换要删除的用户的所有引用。 通过获取该用户表的依赖关系,是否可以使用任何sql脚本执行此操作?
[更新] 我正在寻找一个自动识别依赖关系并交换用户ID的脚本
答案 0 :(得分:0)
是的,如果您可以先创建新用户,并在插入后,根据条件更新参考。
像
declare @newUserid int , @olduserid
insert user values (colval1, colval2,..)
select @newUserid = @@identity
update tablename set userid = @newUserid where userid = @olduserid
如果是多个用户,则为更新语句创建动态查询。
Declare @query nvarchar(max)
Set @query = 'update tablename set userid = ' + @newUserid + ' where userid in ( ' + @olduserid + ')'
EXEC sp_executesql @query
最后,您可以删除用户。
<强>更新强> 对于自动配合进程,您使用Sql Jobs或使用触发器。您可以安排Sqljob,而只要插入,更新,删除发生,就会在表上触发触发器。
所以触发器的缺点是性能观点,而对于sql-job,你需要sqlagent功能,这在sqlserver enterprice版或者equilant中可用,快递版没有Sqlagent。
我建议,无论何时插入或更新,您都可以使用或说出另一个程序,根据当前的方案更新记录。
如果userid = 1或者usertype =&#39; guest&#39;则不会向我们提供任何方案。更新,然后更改数据等。
答案 1 :(得分:0)
Cascade Update
中有一些名为SQL SERVER
的内容。 ON UPDATE CASCADE
选项指定如果尝试更新行中的键值,其中键值由其他表中现有行中的外键引用,则所有外键值也会更新为为密钥指定的新值。如果还在目标表上定义了级联引用操作,则还会对这些表中更新的键值采取指定的级联操作
检查 here 了解更多信息
ALTER TABLE childtablename
ADD CONSTRAINT FK_name FOREIGN KEY(childcolumn) REFERENCES parenttable (parentcolumn) ON UPDATE CASCADE
答案 2 :(得分:0)
是的,可以通过编程方式识别表的依赖关系(外键约束)。 您需要的是sys-Tables。
特别需要:
考虑到这一点
SELECT
ReferencedTable.name AS ReferencedTableName,
ReferencedColumn.name AS ReferencedColumnName,
DependingTable.name AS DependingTableName,
DependingColumn.name AS DependingColumnName
FROM sys.all_objects AS DependingTable
INNER JOIN sys.foreign_key_columns AS ForeignKeys
ON DependingTable.object_id = ForeignKeys.parent_object_id
INNER JOIN sys.all_objects AS ReferencedTable
ON ForeignKeys.referenced_object_id = ReferencedTable.object_id
INNER JOIN sys.columns AS DependingColumn
ON ForeignKeys.parent_object_id = DependingColumn.object_id AND ForeignKeys.parent_column_id = DependingColumn.column_id
INNER JOIN sys.columns AS ReferencedColumn
ON ForeignKeys.referenced_object_id = ReferencedColumn.object_id AND ForeignKeys.referenced_column_id = ReferencedColumn.column_id
WHERE ReferencedTable.name = 'UserTable'
将为您提供一个结果集,每行代表一个现有外键,包含您引用的表名,引用的列名,当然还有依赖(引用)表及其列的名称。现在我们可以更进一步:
鉴于您知道将删除哪个用户ID以及哪个id将作为替代,您可以让最后一个查询为您生成更新语句,以下代码就是这样做的,并且最重要的是使用游标立即执行这些陈述(您只需要设置@tableName
,@sourceValue
和@targetValue
):
DECLARE @tableName NVARCHAR(MAX) = 'UserTable'
DECLARE @sourceValue INT = 3
DECLARE @targetValue INT = 1
DECLARE @sqlStatements TABLE (ID INT PRIMARY KEY IDENTITY(1,1), cmdTxt NVARCHAR(MAX))
INSERT @sqlStatements (cmdTxt)
SELECT
'UPDATE ' + DependingTable.name + ' SET ' + DependingColumn.name + ' = ' + CAST(@targetValue AS NVARCHAR(MAX)) +
' WHERE ' + DependingColumn.name + ' = ' + CAST(@sourceValue AS NVARCHAR(MAX))
FROM sys.all_objects AS DependingTable
INNER JOIN sys.foreign_key_columns AS ForeignKeys
ON DependingTable.object_id = ForeignKeys.parent_object_id
INNER JOIN sys.all_objects AS ReferencedTable
ON ForeignKeys.referenced_object_id = ReferencedTable.object_id
INNER JOIN sys.columns AS DependingColumn
ON ForeignKeys.parent_object_id = DependingColumn.object_id AND ForeignKeys.parent_column_id = DependingColumn.column_id
INNER JOIN sys.columns AS ReferencedColumn
ON ForeignKeys.referenced_object_id = ReferencedColumn.object_id AND ForeignKeys.referenced_column_id = ReferencedColumn.column_id
WHERE ReferencedTable.name = @tableName
DECLARE @currentCmd NVARCHAR(MAX)
DECLARE cmd_cursor CURSOR FOR
SELECT cmdTxt FROM @sqlStatements ORDER BY ID ASC
OPEN cmd_cursor
FETCH NEXT FROM cmd_cursor
INTO @currentCmd
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC sp_executesql @currentCmd
FETCH NEXT FROM cmd_cursor
INTO @currentCmd
END
CLOSE cmd_cursor;
DEALLOCATE cmd_cursor;
您可能应该在事务中封装整个事情并在最后做一些令人安慰的select语句,告诉您在最终提交更改之前没有破坏任何内容。