Sql server 循环和插入/更新的最佳解决方案
我很想知道是否有比我现有的更好/更优化的解决方案,因为它使用游标,我知道从性能角度来看,游标不是很好 基本上,我的要求是检查一个ID是否存在许多设置,然后相应地更新或插入它们 为此,我必须:Sql server 循环和插入/更新的最佳解决方案,sql-server,Sql Server,我很想知道是否有比我现有的更好/更优化的解决方案,因为它使用游标,我知道从性能角度来看,游标不是很好 基本上,我的要求是检查一个ID是否存在许多设置,然后相应地更新或插入它们 为此,我必须: DECLARE @UserId UNIQUEIDENTIFIER = '{PUT-GUID-HERE}' 然后我声明一个表变量,将设置名称和值添加到其中,总共大约有15个 DECLARE @SettingsToCheck TABLE (SettingName varchar(100), SettingVa
DECLARE @UserId UNIQUEIDENTIFIER = '{PUT-GUID-HERE}'
然后我声明一个表变量,将设置名称和值添加到其中,总共大约有15个
DECLARE @SettingsToCheck TABLE (SettingName varchar(100), SettingValue varchar(100)
INSERT INTO @SettingsToCheck ('Setting1', 'Setting1 Value') --Repeat...
DECLARE @CurrentSettingName varchar(100)
DECLARE @CurrentSettingValue varchar(100)
DECLARE Settings_Cursor CURSOR FOR SELECT SettingName, SettingValue FROM @SettingsToCheck
OPEN Settings_Cursor
FETCH NEXT FROM Settings_Cursor INTO @CurrentSettingName, @CurrentSettingValue
WHILE @@FETCH_STATUS = 0
BEGIN
IF EXISTS (SELECT * FROM MyActualTable WHERE UserID = @UserId AND SettingName = @CurrentSettingName)
BEGIN
UPDATE MyActualTable SET SettingValue = @CurrentSettingValue WHERE UserID = @UserId AND SettingName = @CurrentSettingName
END
ELSE
BEGIN
INSERT INTO MyActualTableVALUES (NEWID(), @UserId, GETDATE(), @CurrentSettingName, @CurrentSettingValue)
END
FETCH NEXT FROM Settings_Cursor INTO @CurrentSettingName, @CurrentSettingValue
END
CLOSE Settings_Cursor
DEALLOCATE Settings_Cursor
我知道这个问题要接受意见,但我不知道还有其他选择
编辑:
SettingName | SettingValue
____________________________
Setting1 | Setting1Value
SettingName | SettingValue
____________________________
Setting1 | Setting1ValueUPDATED
Setting2 | NewSetting
可能存在某些/无或所有设置已存在的情况。但这里有一个例子
之前:
SettingName | SettingValue
____________________________
Setting1 | Setting1Value
SettingName | SettingValue
____________________________
Setting1 | Setting1ValueUPDATED
Setting2 | NewSetting
之后:
SettingName | SettingValue
____________________________
Setting1 | Setting1Value
SettingName | SettingValue
____________________________
Setting1 | Setting1ValueUPDATED
Setting2 | NewSetting
您可以按如下方式使用“合并”
DECLARE @SettingsToCheck TABLE
(
SettingName varchar(100)
,SettingValue varchar(100)
)
DECLARE @ActualTable TABLE
(
SettingName varchar(100)
,SettingValue varchar(100)
)
INSERT INTO @SettingsToCheck
VALUES
('Setting1', 'Setting1 Value') --Repeat...
,('Setting2', 'Setting2 Value')
,('Setting3', 'Setting3 Value')
,('Setting4', 'Setting45 Value')
,('Setting5', 'Setting5 Value')
,('Setting6', 'Setting6 Value')
,('Setting7', 'Setting7 Value')
INSERT INTO @ActualTable
VALUES
('Setting4', 'Setting4 Value')
MERGE INTO @ActualTable AS target
USING @SettingsToCheck AS source
ON target.SettingName = source.SettingName
WHEN MATCHED THEN
UPDATE SET target.SettingValue = source.SettingValue
WHEN NOT MATCHED BY TARGET THEN
INSERT (SettingName, SettingValue)
VALUES (source.SettingName, source.SettingValue);
Select * from @ActualTable
我知道人们喜欢使用合并,但我更喜欢将它们与各自的任务分开。Aaron Bertrand在此处记录了MERGE的一些问题:, 但我不确定有多少人仍然坚持这样做 无论如何,这是另一种选择:
CREATE TABLE #SettingsToCheck
(
SettingName varchar(100)
,SettingValue varchar(100)
)
CREATE TABLE #ActualTable
(
SettingName varchar(100)
,SettingValue varchar(100)
)
INSERT INTO #SettingsToCheck
VALUES
('Setting1', 'Setting1 Value') --Repeat...
,('Setting2', 'Setting2 Value')
,('Setting3', 'Setting3 Value')
,('Setting4', 'Setting45 Value')
,('Setting5', 'Setting5 Value')
,('Setting6', 'Setting6 Value')
,('Setting7', 'Setting7 Value')
INSERT INTO #ActualTable
VALUES
('Setting4', 'Setting4 Value')
UPDATE #ActualTable
SET SettingValue = t2.SettingValue
FROM #ActualTable t1
INNER JOIN #SettingsToCheck t2 on t1.SettingName = t2.SettingName
INSERT INTO #ActualTable(SettingName,SettingValue)
SELECT t1.SettingName,t1.SettingValue
FROM #SettingsToCheck t1
LEFT JOIN #ActualTable t2 on t1.SettingName = t2.SettingName
WHERE t2.SettingName IS NULL
select * from #ActualTable
不循环将是第一步;您正在编写SQL而不是C。在SQL中,基于集合的方法几乎总是比循环执行得快(在某些情况下,这是不正确的,所以“基于集合的循环”)。样本数据和预期结果在这里会有很大帮助。我可以重复IF-EXISTS块进行15个左右的设置,但这将变得非常不可读,但如果需要,我很乐意做出牺牲。代码运行良好,因此预期结果只是表中的更新值;我看不到你的设计,但我怀疑你能在一个声明中做到这一点。如果没有样本数据和预期结果,就无法提出更多建议。我已经用一个非常基本的前后示例更新了我的问题。这有帮助吗?谢谢,今天下午我将尝试一下。我已经使用SettingName来识别记录。您可以在该条件下添加UserId。让我知道任何反馈。。。