2009-11-13 4 views
25

J'ai une fonction personnalisée, et j'essaye de créer une colonne persistante en utilisant cette fonction.La colonne calculée ne peut pas être conservée

Il me donne erreur suivante.

La colonne calculée 'FormattedSSN' dans la table 'SomeTable' ne peut pas être persistante car la colonne est non déterministe.

est la fonction ici:

ALTER FUNCTION [dbo].[FormatSSN]() 
RETURNS VARCHAR(11) 
AS 
BEGIN 
    return ''; 
END 

Voici la requête pour ajouter la colonne à l'aide de la fonction:

ALTER TABLE SomeTable 
ADD FormattedSSN as dbo.FormatSSN() PERSISTED 

S'il vous plaît indiquer s'il y a un moyen de sortir. Merci.

Répondre

36

Ajouter AVEC SCHEMABINDING à la fonction comme ceci:

ALTER FUNCTION [dbo].[FormatSSN] 
(
@SSN VARCHAR(9) 
) 
RETURNS CHAR(11) 
WITH SCHEMABINDING 
AS 
BEGIN 
    your stuff here 
END 

puis lancer pour vérifier:

IF OBJECTPROPERTY (OBJECT_ID(N'[dbo].[FormatSSN]'),'IsDeterministic') = 1 
    PRINT 'Function is detrministic.' 
ELSE IF OBJECTPROPERTY (OBJECT_ID(N'[dbo].[FormatSSN]'),'IsDeterministic') = 0 
    PRINT 'Function is NOT detrministic' 
GO 

Travaux ici.

+1

Génial. Mais comment cette fonction est-elle différente (comportement) de la fonction régulière? –

+0

Merci. Je connaissais SCHEMABINDING dans d'autres contextes (par exemple, les vues). Il semble que cela marchera à peu près pareil ici. Toute modification apportée à la table provoquera une erreur. –

5

Que diriez-vous préciser la définition directement:

ALTER TABLE SomeTable 
ADD FormattedSSN as 
    case when len(EmployeeSSN) = 9 then 
      substring(EmployeeSSN, 1, 3) + '-' + 
      substring(EmployeeSSN, 4, 2) + '-' + 
      substring(EmployeeSSN, 6, 4) 
    else EmployeeSSN end 
PERSISTED 
+0

Yay! ... cela a fonctionné:) ... Pouvez-vous expliquer pourquoi? Quelle est la différence entre ceci et celui que j'ai posté? Ça va marcher de la même façon? –

+2

Le moteur ne peut pas dire quels effets secondaires l'UDF pourrait avoir, car il pourrait être modifié plus tard, et le plan mis en cache est recalculé chaque fois qu'il est exécuté. Lorsque vous représentez la colonne calculée en tant qu'expression SQL, elle sait qu'il n'y a pas d'effets secondaires non déterministes. –

3

Au lieu d'appeler l'UDF, définissez l'expression de la colonne calculée à

Case When Len(EmployeeSSN) = 0 Then 
     SUBSTRING(EmployeeSSN, 1, 3) + '-' + 
     SUBSTRING(EmployeeSSN, 4, 2) + '-' + 
     SUBSTRING(EmployeeSSN, 6, 4) 
    Else EmployeeSSN End 

Dans le script Créer un tableau, vous pouvez ajouter une colonne:

[NewColumnName] As 
    (Case When len([UpdateUserId])=(0) T 
     Then (((substring([UpdateUserId],(1),(3))+'-')+ 
       substring([UpdateUserId],(4),(2)))+'-')+ 
       substring([UpdateUserId],(6),(4)) 
     Else [UpdateUserId] End) PERSISTED, 
0

Créer une colonne non calculée de type de données approprié. Créez un déclencheur d'insertion (et un déclencheur de mise à jour si les données changent). Vous pouvez ensuite conserver la sortie de la fonction dans une colonne.

ALTER TABLE SomeTable ADD FormattedSSN VARCHAR(11) 
GO 

CREATE TRIGGER dbo.TR_I_SomeTable ON dbo.SomeTable AFTER INSERT 
AS 
BEGIN 
    SET NOCOUNT ON; 

    update s 
    set s.FormattedSSN = dbo.FormatSSN() 
    from SomeTable AS s 
     join inserted i on i.id = s.id 

END 
GO 
Questions connexes