有人使用架构部署了一个SQL表
ConfigOptions
name VARCHAR(50)
value VARCHAR(50)
以及保存选项的以下逻辑:
int i = ExecuteNonQuery("UPDATE ConfigOptions SET value=@value WHERE name=@name");
if(i==0) i = ExecuteNonQuery("INSERT INTO ConfigOptions (name,value) (@name,@value)");
我们现在看到这个表格上堆满了重复项,我们想要改变它。
据我所知,逻辑是:只要UPDATE
影响零行,就会插入另一行。如果我没有弄错的话,这可能是由以下原因引起的:
@name
名称的行不存在或@value
因此,所有具有相同名称的行应该是完全重复的。如果现在,某些事情是完全错误的(并且行为可能未定义)。
现在我必须解决重复问题,所以我想在name
上添加PK。在我这样做之前,我必须删除所有具有重复名称的行,只保留其中一行。
在安装程序中(只允许安装程序更改架构),我手边只有SQL查询,因此无法使用C#逻辑执行此操作:
Dictionary<string, int> dic = new Dictionary<string, int>();
SqlDataReader sdr = ExecuteReader("SELECT name,COUNT(value) FROM ConfigOptions GROUP BY name HAVING COUNT(value)>1");
while (sdr.Read()) dic.Add(sdr.GetString(0), sdr.GetInt32(1));
sdr.Close();
foreach (var kv in dic) {
AddParameter("@name", System.Data.SqlDbType.VarChar, 50, kv.Key);
ExecuteNonQuery("DELETE TOP " + (kv.Value - 1) + " FROM ConfigOptions WHERE name=@name");
}
ExecuteNonQuery("ALTER TABLE program_options ADD PRIMARY KEY (name)");
有没有办法把它放到SQL逻辑中?
答案 0 :(得分:1)
使用%%physloc%%
,该行的phys(ical)loc(ation)应该可以做到这一点:
DELETE FROM ConfigOptions
WHERE %%physloc%% NOT IN (
SELECT MIN(%%physloc%%)
FROM ConfigOptions
GROUP BY name);
完成此清理后,您可以将主键添加到表中。
注意:这将为每个name
只留一行。如果value
列在具有相同name
的两个记录中不同,您将丢失最新记录。如果您想更改此设置,请使用GROUP BY name, value
。