2010-07-07 6 views
1

Je suis en train de changer toutes les valeurs NULL dans une colonne INT à une valeur incrémentiel en utilisant une instruction comme ceci:Mise à jour avec fonction de la valeur semble seulement d'évaluer la fonction une fois

UPDATE [TableName] SET [ColumnName] = dbo.FunctionName() WHERE [ColumnName] IS NULL 

où la fonction ressemble ceci:

CREATE FUNCTION FunctionName() RETURNS INT AS 
BEGIN 
    RETURN (select MAX(ColumnName) + 1 from TableName) 
END 

mais le résultat est que toutes les valeurs qui étaient NULL sont maintenant réglés à la même valeur (par exemple supérieure à 1 au maximum avant la déclaration a été appelé).

Est-ce le comportement attendu? Si oui, comment pourrais-je obtenir le résultat que je cherche?

Je voudrais éviter d'utiliser une colonne d'auto-incrément comme tout ce que je veux c'est l'unicité, l'incrémentation est juste un moyen d'y arriver.

+0

Vous obtiendrez le résultat que vous êtes après à l'aide d'une colonne autoincrement. Votre raison de ne pas vouloir en utiliser une s'applique autant à votre hack qu'à l'auto-incrémentation réelle. –

+0

@Anon: les valeurs de cette colonne sont des identifiants uniques définis en dehors de notre système, qui ne s'auto-incrémentent définitivement pas. Je veux seulement le comportement incrémentiel pour les inconnus existants. – Eltariel

Répondre

4

Oui, c'est par conception, il s'appelle Halloween protection. Pour obtenir ce que vous voulez (c'est un une fois) utiliser un CTE actualisable:

with cte as (
SELECT Column, 
ROW_NUMBER() OVER() as rn 
FROM Table 
WHERE Column IS NULL) 
UPDATE t 
SET t.Column = m.max + t.rn 
FROM cte t 
JOIN (
SELECT MAX(Column) as max 
FROM Table) m; 
+0

Merci pour ça. SQL2008 se plaignait un peu de la syntaxe, mais ils étaient triviaux à corriger: 'ROW_NUMBER() OVER()' -> 'ROW_NUMBER() OVER (ORDER BY col)', et 'JOIN (...) m' - > 'JOIN (...) m ON 1 = 1' – Eltariel

Questions connexes