MSSQL C# 查询仅在值唯一时添加行
MSSQL C# query Only add row if value is unique
我有一个简单的 c# 应用程序,它使用以下内容写入数据库。
IF EXISTS (SELECT * FROM Table WHERE deviceName='deviceNAMEDATA')
UPDATE HeartBeat
SET DeviceName = 'DEVICENAMEDATA',
LastConnect = 'DATETIMEDATA'
ELSE
INSERT INTO HeartBeat
VALUES('DeviceNAMEDATA', 'DATETIMEDATA')
DEVICENAMEDATA 和 DATETIMEDATA 使用字符串生成器替换为设备名称和时间。
我把它 运行 放了一个小时,一切似乎都正常,但我没有得到任何重复记录,但是在 运行 放了 24 小时后,数据库有大约 20 条重复记录。
是否有更好的方法来确保永远不会创建具有相同设备名称的两行?
Is there a better way of ensuring that two rows with the same device name are never created ?
是,让数据库使用唯一的 constraint/index:
确保数据完整性
alter table t add constraint unq_t_deviceName unique (deviceName);
您需要调整代码以捕获 insert
上的错误。如果这是 T-SQL 代码,您可以使用 try
/catch
块。
问题出在您的更新语句上 - 您正在更新两列,而不是使用 Where
子句中的 DeviceName
列。它应该是这样的:
UPDATE HeartBeat
SET LastConnect = 'DATETIMEDATA'
WHERE DeviceName = 'DEVICENAMEDATA'
话虽如此,您可能应该将 DeviceName
用作 table 的 primary key,这将使其不可能具有多个值。
此外,关于 "upsert" 的主题,您应该阅读 Dan Guzman 的 blog post 关于如何在 SQL 服务器中避免 "upsert" 中的竞争条件。
还有一件事 - 您应该始终在插入语句中指定列列表。
我会这样写:
SET NOCOUNT, XACT_ABORT ON
BEGIN TRY
BEGIN TRANSACTION
IF EXISTS
(
SELECT *
FROM Table
WITH (UPDLOCK, HOLDLOCK)
WHERE deviceName='deviceNAMEDATA'
)
UPDATE HeartBeat
SET LastConnect = 'DATETIMEDATA'
WHERE DeviceName = 'DEVICENAMEDATA'
ELSE
INSERT INTO HeartBeat (DeviceName, LastConnect)
VALUES('DeviceNAMEDATA', 'DATETIMEDATA')
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION
END CATCH
我有一个简单的 c# 应用程序,它使用以下内容写入数据库。
IF EXISTS (SELECT * FROM Table WHERE deviceName='deviceNAMEDATA')
UPDATE HeartBeat
SET DeviceName = 'DEVICENAMEDATA',
LastConnect = 'DATETIMEDATA'
ELSE
INSERT INTO HeartBeat
VALUES('DeviceNAMEDATA', 'DATETIMEDATA')
DEVICENAMEDATA 和 DATETIMEDATA 使用字符串生成器替换为设备名称和时间。
我把它 运行 放了一个小时,一切似乎都正常,但我没有得到任何重复记录,但是在 运行 放了 24 小时后,数据库有大约 20 条重复记录。
是否有更好的方法来确保永远不会创建具有相同设备名称的两行?
Is there a better way of ensuring that two rows with the same device name are never created ?
是,让数据库使用唯一的 constraint/index:
确保数据完整性alter table t add constraint unq_t_deviceName unique (deviceName);
您需要调整代码以捕获 insert
上的错误。如果这是 T-SQL 代码,您可以使用 try
/catch
块。
问题出在您的更新语句上 - 您正在更新两列,而不是使用 Where
子句中的 DeviceName
列。它应该是这样的:
UPDATE HeartBeat
SET LastConnect = 'DATETIMEDATA'
WHERE DeviceName = 'DEVICENAMEDATA'
话虽如此,您可能应该将 DeviceName
用作 table 的 primary key,这将使其不可能具有多个值。
此外,关于 "upsert" 的主题,您应该阅读 Dan Guzman 的 blog post 关于如何在 SQL 服务器中避免 "upsert" 中的竞争条件。
还有一件事 - 您应该始终在插入语句中指定列列表。
我会这样写:
SET NOCOUNT, XACT_ABORT ON
BEGIN TRY
BEGIN TRANSACTION
IF EXISTS
(
SELECT *
FROM Table
WITH (UPDLOCK, HOLDLOCK)
WHERE deviceName='deviceNAMEDATA'
)
UPDATE HeartBeat
SET LastConnect = 'DATETIMEDATA'
WHERE DeviceName = 'DEVICENAMEDATA'
ELSE
INSERT INTO HeartBeat (DeviceName, LastConnect)
VALUES('DeviceNAMEDATA', 'DATETIMEDATA')
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION
END CATCH