Există un operator OR exclusiv în T-SQL? (Programare, Tsql)

Jonathan Allen a intrebat.

Aceasta este declarația mea

IF (@UserName IS NULL AND @EditorKey IS NULL) OR (@UserName IS NOT NULL AND @EditorKey IS NOT NULL) BEGIN
    RAISERROR ('One of @UserName, @EditorKey must be non-null.', 15, 0)
    RETURN
END

Ceea ce vreau este să pot face ceva de genul acesta:

IF (@UserName IS NOT NULL) XOR (@EditorKey IS NOT NULL) BEGIN
    RAISERROR ('One of @UserName, @EditorKey must be non-null.', 15, 0)
    RETURN
END

Pentru doi parametri, nu este o problemă atât de mare, dar unele procs au trei sau patru unde doar unul poate fi trecut și restul ar trebui să fie nul.

Comentarii

  • Prima ta declarație, (a AND b) OR (NOT a AND NOT b), , este un înlocuitor pentru a EQU b (echivalență logică), care este, din punct de vedere logic, negația lui XOR. Aceasta din urmă este reprezentată, de exemplu, în felul următor: (a AND NOT b) OR (NOT a AND b) sau așa: (a OR b) AND (NOT a OR NOT b). –  > Por Andriy M.
  • posibil duplicat al operatorului XOR din T-SQL –  > Por BuZZ-dEE.
3 răspunsuri
Chris Fulstow

Nu este foarte succint, dar ați putea extinde logica astfel:

WHERE
    (NOT ((@UserName IS NOT NULL) AND (@EditorKey IS NOT NULL))) AND
    ((@UserName IS NOT NULL) OR (@EditorKey IS NOT NULL))

Sau folosiți operatorul XOR bitwise XOR (^):

WHERE
    (CASE WHEN (@UserName IS NOT NULL) THEN 1 ELSE 0 END) ^
    (CASE WHEN (@EditorKey IS NOT NULL) THEN 1 ELSE 0 END) = 1

Puteți utiliza o abordare similară în cazul în care există trei sau patru parametri, iar exact unul trebuie să aibă o valoare:

WHERE
    (CASE WHEN (@Var1 IS NOT NULL) THEN 1 ELSE 0 END) +
    (CASE WHEN (@Var2 IS NOT NULL) THEN 1 ELSE 0 END) +
    (CASE WHEN (@Var3 IS NOT NULL) THEN 1 ELSE 0 END) +
    (CASE WHEN (@Var4 IS NOT NULL) THEN 1 ELSE 0 END) = 1

Comentarii

  • Prima jumătate a expresiei este în esență ((@UserName IS NULL) OR (@EditorKey IS NULL)), , în funcție de legile lui De Morgan. –  > Por Andriy M.
  • @Andriy De acord, tratez (@UserName IS NOT NULL) ca pe o expresie booleană de caz general, fără a simplifica nimic din logică. –  > Por Chris Fulstow.
  • Nu este drăguț, dar cel puțin se va scala. –  > Por Jonathan Allen.
  • Este ușor nesatisfăcător dacă nu există o modalitate mai bună de a face acest lucru. Principala limitare pare să fie lipsa unui tip de date bool adecvat în TSQL. –  > Por Chris Fulstow.
Quillbreaker

Ca un trișor, puteți face:

If @[email protected] is null and coalesce(@UserName,@EditorKey) is not null

Este mai scurt, dar acesta ar putea fi singurul lucru pe care îl are în favoarea sa.

Denis de Bernardy

Există un XOR bitwise XOR, dar nu este neapărat ceea ce vrei tu:

http://msdn.microsoft.com/en-us/library/ms190277.aspx

În cazul dvs. particular, mi se pare mai imediat să o rescrieți astfel:

IF (@UserName IS NULL) = (@EditorKey IS NULL) BEGIN

Comentarii

  • Îmi place. Pentru a transforma acest lucru în XOR adevărat, ((logical condition) <> (other logical condition)). –  > Por Ben Mosher.
  • Corectați-mă dacă greșesc, dar tipul de date boolean al serverului SQL nu este comparabil? „IF (NULL IS NULL) = (NULL IS NULL) PRINT ‘COMPARABLE'” are ca rezultat „Sintaxa incorectă lângă ‘='”. –  > Por shannon.
  • @shannon: Nu ar trebui să înfășurați acel print între begin/end? –  > Por Denis de Bernardy.
  • @Denis: Este cu siguranță o formă mai bună, dar nu este necesară pentru operațiile simple. Rezultatul este același. Poți să faci o încercare și să-mi spui dacă greșesc? Scriu constrângeri similare chiar în acest moment. Mi-ar plăcea să folosesc această tehnică și să vă votez în sus. –  > Por shannon.
  • Tbh, am tradus pur și simplu ceea ce fac Postgres, unde funcționează foarte bine… Folosesc ocazional construcția în constrângerile de verificare pentru a face câmpurile să se excludă reciproc. –  > Por Denis de Bernardy.

Tags: