У меня очень простой вопрос о транзакциях. (в 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
Но это не работает. Может ли кто-нибудь предоставить мне пример рабочей транзакции, которая применяет эту логику?
ОБНОВЛЕНИЯ:
Последовательность
Эта характеристика означает, что база данных должна быть согласованной до и после транзакции.
Ни в коем случае частичная транзакция не может быть зафиксирована в базе данных, так как это приведет к ее несовместимости.
Не означает ли это, что в возможна несогласованность транзакций?
ОБНОВЛЕНИЕ:
Некоторые спрашивают меня, почему я не использовал обновление в этом случае. Вроде сложно, но я попробую: необходимый sql был частью сценария публикации, который строит таблицы из представлений, а затем обновляет эти таблицы. Поскольку представления содержали модель публикации, изменения представления были сделаны там и только там. Остальная часть сценария не может полагаться на имена столбцов для выполнения обновления.
Конечно, я мог бы запросить эти имена столбцов, но в то время это было хлопотно, поэтому я решил не делать этого, а вместо этого отбросил ограничения и перестроил их. Теперь я должен признать, что не чувствовал себя комфортно с этим решением, поэтому теперь я использую действительно обновление вместо этого. Я написал 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