如何使用范围内的唯一编号更新SQL表

时间:2011-11-25 14:17:33

标签: sql sql-update

(这是我今天早些时候发布的the answer by "onedaywhen" on a question的后续内容。)

大家好。假设我有一个表MyTable,其中包含两个int字段,PrimaryKeyMyNumber。 (和其他与此问题无直接关系的领域)。 MyNumber具有唯一约束和检查约束,将其限制为BETWEEN 1 AND n。 (现在让我们说n=5。)

1,2  
2,NULL  
3,5  
4,NULL  
5,NULL  
6,1  
7,NULL

如何编写UPDATE来更改PrimaryKey=2的记录,以便MyNumber具有非NULL值?我不关心它有什么价值,只要它不是NULL并且满足它的唯一和范围内的两个限制。

我正在使用MS SQL Server,但我希望有一个使用标准SQL的答案。

(我也希望不必有一个数字1到n作为内容的表。)

非常感谢。

3 个答案:

答案 0 :(得分:0)

查找MS-SQL的@ROW_NUMBER函数,我现在无法想到代码,而且我不在我的数据库服务器附近做一些测试,但如果内存服务,@ ROW_NUMBER与“IS NOT NULL”检查相关联应该可以帮助您实现目标。

@ROW_NUMBER文档:http://msdn.microsoft.com/en-us/library/ms186734.aspx

对于其他SQL版本,我目前无法想到解决方案。

答案 1 :(得分:0)

WITH CTE AS (
    SELECT 1 N
    UNION ALL
    SELECT N + 1 FROM CTE WHERE N < 5
)
UPDATE MyTable
SET MyNumber = (
    SELECT TOP 1 N FROM CTE
    WHERE NOT EXISTS (SELECT * FROM MyTable WHERE MyNumber = N)
)
WHERE PrimaryKey = 2

用简单的英语:

  • 生成1到5之间的整数(WITH CTE AS ...)。
  • 选择 MyNumber SELECT TOP 1 ...)中已存在的第一个整数。
  • PrimaryKey = 2 UPDATE ...)标识的行中将该整数分配给 MyNumber

如果此查询无法找到合适的值,则只需将 MyNumber 设置为NULL。


警告:这可能仍然在并发环境中对 MyNumber 的UNIQUE约束进行调整(即,当两个并发执行的事务尝试并行运行同一查询时)。因此,您必须准备好在必要时重试查询。

答案 2 :(得分:0)

我不禁要指出,下一版本的SQL(代号Denali)将支持SEQUENCES,在这种情况下显然是理想的。

代码看起来像这样:

CREATE SEQUENCE Count1to5
  START WITH 1
  INCREMENT BY 1
  MAX VALUE 5;

我不确定如何或者是否能够使用where来跳过更新的值,而我没有使用beta设置测试服务器,但似乎值得一提的是此解决方案将即将推出。