2012-04-24 2 views
0

substrings Pardonnez-moi, si ce problème est résolu dans un autre billet sur SO ... Je l'ai cherché, mais ne peut pas sembler trouver tout à fait la bonne solution ...SQL contrainte de vérification sur

Je suis créer une table. La colonne 'Creditor' est entièrement numérique, SAUF que le dernier char peut être un tiret. Cela signifie que des exemples tels que '1234-', '92846293' et ainsi de suite sont valides et que '12354-53', '12345K' ne sont pas valides. La longueur de la chaîne n'est pas fixe (sauf s'il s'agit d'un varchar (50)).

Je ne sais pas comment créer la contrainte de vérification.

Aidez s'il vous plaît!

+0

Ce n'est généralement pas quelque chose que vous pouvez faire avec une contrainte de vérification ... certainement pas dans ANSI SQL. Avec quelle plate-forme travaillez-vous? –

Répondre

2

Vous n'avez pas indiqué votre SGBD. Pour PostgreSQL ce serait:

alter table foo 
    add constraint check_creditor check (creditor ~ '^([0-9]+)\-?$'); 

Pour Oracle serait:

alter table foo 
    add constraint check_creditor check (regexp_like(creditor, '^([0-9]+)\-?$')) 

Si votre SGBD prend en charge les expressions régulières, vous devez utiliser la syntaxe pour votre SGBD pour vérifier cela. L'expression régulière elle-même '^([0-9]+)\-$' sera probablement la même cependant.

+0

Je ne suis pas un expert RegEx, mais vu que le caractère final est optionnel, ne devrait-il pas être:^([0-9] +) -? $ – weenoid

+0

@weenoid: Right. J'ai mal interprété "peut être" comme "doit être";). Merci –

0

Pour SQL Server:

Test 1: tous les caractères sauf le dernier sont numériques (alternativement, il n'existe pas un caractère qui est non numérique):

CHECK (SUBSTRING(Creditor, 1, LEN(Creditor) - 1) NOT LIKE '%[^0-9]%') 

Test 2: la dernier caractère est numérique ou un tiret:

CHECK (SUBSTRING(Creditor, LEN(Creditor), 1) LIKE '%[0-9-%]') 

qui précède suppose Creditor ne peut pas être la chaîne vide-à-dire

CHECK (LEN(Creditor) > 0) 

Juste pour le plaisir:

CHECK (REVERSE(CAST(REVERSE(Creditor) + REPLICATE(0, 50) AS CHAR(50))) 
      LIKE REPLICATE('[0-9]', 49) + '[0-9-]') 
1

Merci pour vos réponses.

La proposition sur '%[^0-9]%' était une belle révélation pour moi, car je ne connaissais pas l'opérateur ^ avant.

J'ai effectué deux versions de la contrainte requise. Un utilisant "seulement" AND, OR, sous-chaînes et isnumeric. Pas d'indices fantaisistes ou d'exclusions. Was waaaay trop longtemps. L'autre version comprenait AND, OR, sous-chaînes et insmuric, mais avec l'inclusion des opérations^proposées. Ça a l'air beaucoup plus agréable. Puis, à la fin, je suis allé avec une troisième solution :-) Ajout d'une colonne bool sur la base de données, RequiresCreditorValidation, et implémenté une regex dans mon code C#.

Pour d'autres qui espèrent tirer profit des contrôles qui en résultent, les voici. En commençant par le "laid" un:

CHECK ((val NOT IN ('+','-') AND (ISNUMERIC(val) = 1) OR 
(ISNUMERIC(SUBSTRING(val, 1, DATALENGTH(val) -1))) = 1) AND 
((SUBSTRING(val, (DATALENGTH(val)),1) LIKE '[0-9]') OR 
(SUBSTRING(val, DATALENGTH(val),1) = '-')) AND 
(SUBSTRING(val, 1, 1) NOT IN ('+','-'))) 

Le second:

CHECK ((SUBSTRING(val, 1, DATALENGTH(val) - 1) NOT LIKE '%[^0-9]%') AND 
(SUBSTRING(val, DATALENGTH(val),1) LIKE '%[0-9-]') AND (DATALENGTH(val) > 0) 
AND SUBSTRING(val, 1,1) NOT IN ('+','-')) 

Et puis le Regex:

Merci
var allButLast = kreditorId.Substring(0, kreditorId.Length - 1); 
     if (Regex.Match(allButLast, "[^0-9]").Success) 
      return false; 
     if (!kreditorId.EndsWith("-")) 
      if (Regex.Match(kreditorId, "[^0-9]").Success) 
       return false; 
     return true; 

toutes des réponses bonnes, qualifiés et rapides.

Questions connexes