Это действительно должна быть атомная единица работы для поддержания целостности ваших данных !!! При обновлении нескольких таблиц, которые должны быть синхронизированы, используйте BEGIN и COMMIT / ROLLBACK TRAN или, если у вас Sql Server 2008, используйте новый синтаксис TRY CATCH
BEGIN TRAN
BEGIN TRY
UPDATE dbo.Users
SET Flags = @var
WHERE UserName = 'UserA'
UPDATE dbo.Groups
SET Flags = @var
FROM dbo.Users u INNER JOIN dbo.UsersGroups ug ON u.UserID = ug.UserID
INNER JOIN dbo.Groups g ON g.GroupID = ug.GroupID
WHERE u.UserName = 'UserA'
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH
IF @@TRANCOUNT > 0
COMMIT TRAN
Кроме того, если ваши данные денормализованы для повышения производительности, то это ваше лучшее решение. Если это не так, я рекомендую вам отказаться от одного из столбцов. (Ждет типичного "Это не моя схема, я унаследовал это .. наследие бла ... хе хе:))
PS код внутри блока транзакции вопиющим образом копируется / вставляется из ответа Криса.
EDIT
Есть много комментариев по поводу неоднозначных имен столбцов, но здесь нет ничего плохого в TSQL. Вот полный DML и QUERY, которые я протестировал в MSSMS:
IF NOT EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE
TABLE_NAME='Users')
BEGIN
CREATE TABLE Users
(
UserID INT IDENTITY(1,1) PRIMARY KEY,
UserName NVARCHAR(32) NOT NULL,
RealName NVARCHAR(64) NOT NULL,
Flags NVARCHAR(16) NOT NULL
)
END
GO
IF NOT EXISTS (SELECT ix.name FROM sys.indexes ix WHERE ix.name='IX_Users_UserName')
BEGIN
CREATE UNIQUE INDEX IX_Users_UserName ON Users(UserName)
END
GO
IF NOT EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='Groups')
BEGIN
CREATE TABLE Groups
(
GroupID INT IDENTITY(1,1) PRIMARY KEY,
GroupName NVARCHAR(32) NOT NULL,
Flags NVARCHAR(16) NOT NULL
)
END
GO
IF NOT EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='UsersGroups')
BEGIN
CREATE TABLE UsersGroups
(
UserID INT NOT NULL,
GroupID INT NOT NULL,
CONSTRAINT PK_UsersGroups PRIMARY KEY CLUSTERED (UserID, GroupID),
CONSTRAINT FK_UsersGroups_UserID FOREIGN KEY (UserID) REFERENCES Users(UserID),
CONSTRAINT FK_UsersGroups_GroupID FOREIGN KEY (GroupID) REFERENCES Groups(GroupID),
)
END
GO
DECLARE @count INT = (SELECT COUNT(*) FROM Users)
IF @count = 0
BEGIN
INSERT INTO Users(UserName, RealName, Flags)
SELECT 'USERA', 'User A', 'Flags A'
UNION ALL
SELECT 'USERB', 'User B', 'Flags B'
END
SELECT @count = (SELECT COUNT(*) FROM Groups)
IF @count = 0
BEGIN
INSERT INTO Groups(GroupName, Flags)
SELECT 'Group A', 'Flags A'
UNION ALL
SELECT 'Group B', 'Flags B'
END
SELECT @count = (SELECT COUNT(*) FROM UsersGroups)
IF @count = 0
BEGIN
INSERT INTO UsersGroups(GroupID, UserID)
SELECT 1, 1
UNION ALL
SELECT 2, 2
END
GO
BEGIN TRAN
BEGIN TRY
DECLARE @var NVARCHAR(16)
SET @var = 'New Flags A'
UPDATE dbo.Users
SET Flags = @var
WHERE UserName = 'UserA'
UPDATE dbo.Groups
SET Flags = @var
FROM dbo.Users u INNER JOIN dbo.UsersGroups ug ON u.UserID = ug.UserID
INNER JOIN dbo.Groups g ON g.GroupID = ug.GroupID
WHERE u.UserName = 'UserA'
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH
IF @@TRANCOUNT > 0
COMMIT TRAN
SELECT Flags FROM Users
SELECT Flags FROM Groups