我有一个关于交易的非常简单的问题。 (在SQL Server 2000中,但我想它适用于一般的数据库事务)。交易中允许的状态不一致吗?
tblPrimaryKey
PkId
-----
1
2
3
tblForeignKey
Id ForeignKey
---- -----
1 1
2 2
3 3
4 1
我有2个表,一个引用其他(tblForeingKey.ForeignKey引用tblPrimaryKey.PkID)。现在我有一些逻辑改变了主键的表格,通过删除并重新插入一个键。
删除数据库后,会出现不一致的状态。我观察了我的旧脚本,在那里我首先放弃了这段关系,然后重新创建了它。但我的问题是这样的:我了解到事务是原子的,所以在事务不一致状态下是允许的。
所以我想这样的事情应该工作:
BEGIN TRAN eg
DELETE tblPrimaryKey WHERE PkId = 3
INSERT INTO tblPrimaryKey SELECT 3
COMMIT TRAN eg
但是,这是行不通的。有人能给我提供一个应用这种逻辑的工作事务的例子吗?
更新:
一致性 这一特性意味着数据库应该是之前和交易后一致。
在任何情况下都不能将部分事务提交到数据库,因为这会使数据库处于不一致状态。
这不意味着在的交易不一致是可能的吗?
UPDATE:
有人问我,为什么我没有在这种情况下,使用更新。有点复杂,但我放弃了它:所需的sql是从视图构建表的发布脚本的一部分,然后更新这些表。由于视图包含发布模型,视图的更改在那里进行,并且仅在那里进行。脚本的其余部分不能依赖列名来进行更新。
Ofcourse当然我可以查询这些列名,但它在当时看起来像一个麻烦,所以我选择不去,而是放弃约束重建它们。现在我必须承认,我对这种解决方案感到不舒服,所以现在我确实使用了更新。我写了一个sproc来做到这一点,如果任何人有其他解决方案,请告诉我。
CREATE PROC usp_SyncRecords
(
@tableName1 as nvarchar(255),
@tableName2 as nvarchar(255),
@joinClause as nvarchar(255),
@whereClause as nvarchar(1000)
)
-- this proc updates all fields in table 1 that have corresponding names
-- in table2 to the value of the field in table2.
AS
BEGIN
DECLARE @sqlClause nvarchar(4000)
DECLARE @curFieldName nvarchar(255)
DECLARE @sqlColumnCursorClause nvarchar(1000)
SET @sqlClause = 'UPDATE [' + @tableName1 + '] SET '
-- get FieldNames for second table
SET @sqlColumnCursorClause =
'DECLARE cur CURSOR FAST_FORWARD FOR SELECT name FROM syscolumns ' +
'WHERE id=' + CAST(object_id(@tableName2) as nvarchar(50))
EXEC sp_executeSql @sqlColumnCursorClause
OPEN cur
-- compose sqlClause using fieldnames
FETCH NEXT FROM CUR INTO @curFieldName
WHILE @@fetch_status <> -1
BEGIN
SET @sqlClause = @sqlClause + @curFieldName + '=' +
@tableName2 + '.' + @curFieldName + ','
FETCH NEXT FROM CUR INTO @curFieldName
END
CLOSE cur
DEALLOCATE cur
-- drop last comma
SET @sqlClause = LEFT(@sqlClause,LEN(@sqlClause) -1)
-- adding from/join/where clauses
SET @sqlClause = @sqlClause + ' FROM [' + @tableName1 + '] INNER JOIN [' + @tableName2 + '] '
+ 'ON ' + @joinClause + ' WHERE ' + @whereClause
EXEC sp_executeSQL @sqlClause
END
你究竟在做什么? – 2009-06-07 07:33:02
你是说你不能插入tblPrimaryKey表,因为PkId(或Id)列是身份种子列? – Kane 2009-06-07 07:41:34
@ kane:不,与这里的身份无关 – Peter 2009-06-07 07:57:37