Ich arbeite gerade an einem Tool, das meinen Benutzern hilft, ihren SQL-Code nach SQL-Server 2005 zu portieren. Zu diesem Zweck analysiere ich das SQL in einen Syntaxbaum, analysiere es auf Konstrukte, die Aufmerksamkeit benötigen, modifiziere es und transformiere es zurück in T-SQL.
Auf etwas, das ich unterstützen möchte, ist die "bools sind Werte auch" Semantik anderer RDBMS. Zum Beispiel erlaubt mir MS-Access, select A.x and A.y as r from A
zu schreiben, was in T-SQL unmöglich ist, weil:
Daher konvertiert meine Transformationsroutine die obige Anweisung in folgendes:
%Vor% Was funktioniert, ist aber ärgerlich, weil ich den logischen Ausdruck (der sehr komplex sein kann oder Unterabfragen enthalten kann) duplizieren muss, um zwischen true
, false
und unknown
zu unterscheiden - letzteres soll map auf null. Also frage ich mich, ob die T-SQL-Profis hier einen besseren Weg kennen, dies zu erreichen?
UPDATE: Ich möchte darauf hinweisen, dass Lösungen, die versuchen, die Operanden in der Integer-Domäne zu halten, berücksichtigen müssen, dass einige Operanden logische Ausdrücke an der ersten Stelle sein können . Dies bedeutet, dass eine effiziente Lösung zur Umwandlung eines Bool in einen Wert immer noch erforderlich ist. Zum Beispiel:
%Vor%Ich glaube nicht, dass es eine gute Antwort gibt, es ist wirklich eine Einschränkung von TSQL.
Sie könnten eine UDF für jeden booleschen Ausdruck erstellen, den Sie brauchen
%Vor%verwendet über
%Vor%Boolesche Behandlung
Access scheint die Logik zu verwenden, die 2 Booleans gegeben hat
Ich bin mir nicht sicher, ob andere DBMS (Oracle, DB2, PostgreSQL) mit bool + null umgehen, aber diese Antwort basiert auf der Bestimmung von Access (MySQL und SQLite stimmen zu). Die Tabelle der Ergebnisse ist unten dargestellt.
%Vor%SQL Server Helper 1: Funktion für Boolean von jedem "Einzelwert"
In SQL Server im Allgemeinen füllt diese Funktion die Lücke für die fehlende any value as boolean
-Funktionalität. Es gibt ein ternäres Ergebnis zurück, entweder 1/0 / null - 1 und 0 ist das SQL Server-Äquivalent von wahr / falsch (ohne tatsächlich boolesch zu sein).
Hinweis: Wenn Access als Ausgangspunkt verwendet wird, wird nur der numerische Wert 0 als FALSE ausgewertet Dies verwendet einige SQL Server-Tricks
isnumeric
zurück, schlägt aber bei @v * 1.0
fehl, daher ist ein expliziter Test für LIKE
[0-9]% 'erforderlich, um' isnumeric 'zu reparieren. @v * 1.0
wird benötigt, um einige arithmetische Probleme zu lösen. Wenn Sie die Zeichenfolge "1" in die Funktion ohne * 1.0 übergeben, wird Jetzt können wir die Funktion testen.
%Vor%Sie können es jetzt sicher in einer Abfrage gegen ALLE EINZIGEN SPALTEN verwenden, z. B.
%Vor%SQL Server-Hilfsprogramm 2: Funktion zum Zurückgeben des Ergebnisses von BOOL AND BOOL
Jetzt erstellt der nächste Teil dieselbe Wahrheitstabelle in SQL Server. Diese Abfrage zeigt Ihnen, wie zwei Bit-Spalten interagieren und die einfache CASE-Anweisung, um die gleiche Tabelle wie Access zu erstellen, und Ihre kompliziertere.
%Vor%Dies wird leicht als Funktion ausgedrückt
%Vor%SQL Server-Konvertierung anderer Ausdrücke (nicht eines einzelnen Werts)
Ein Beispiel ist ein "true boolean" in SQL Server, der nicht das Ergebnis einer Spalte sein kann.
%Vor%Muss als
ausgedrückt werden %Vor% Aber wenn A kein skalarer Wert ist, sondern eine Unterabfrage wie (select sum(x)...)
, dann wird, wie Sie sehen können, A zweimal vorkommen und zweimal in der CASE-Anweisung (wiederholt) ausgewertet werden.
ENDGÜLTIGER TEST Jetzt setzen wir alle Konvertierungsregeln in diesem langen Ausdruck
%Vor%Dies führt zu SQL Server (Verkettung der beiden Funktionen und Verwendung von CASE)
%Vor% Zugriff Bool or bool
Der Vollständigkeit halber ist hier die Wahrheitstabelle für Access bool OR bool
. Im Wesentlichen ist es das Gegenteil von UND, also
Die SQL SERVER case-Anweisung wäre daher
%Vor%(das Weglassen einer ELSE-Klausel ist beabsichtigt, da das Ergebnis NULL ist, wenn es weggelassen wird)
BEARBEITEN: Basierend auf zusätzlichen Informationen, die der Frage und den Kommentaren zu einer der vorgeschlagenen Antworten hinzugefügt wurden, formuliere ich diese Antwort:
Wenn Sie nach SQL Server portieren, würde ich erwarten, dass Sie die Daten auch an SQL Server-Typen anpassen. Wenn Sie ein boolesches Feld haben, werden True, False und Unknown auf 1, 0 und NULL als NULL-fähiges BIT-Feld abgebildet.
In diesem Sinne müssen Sie sich nur um die Umwandlung reiner boolescher Werte kümmern. Ausdrücke wie:
%Vor%und:
%Vor%sind bereits in einer praktikablen Form. Bedeutung, Aussagen wie:
%Vor%und:
%Vor%sind bereits korrekt. Sie müssen sich nur darum sorgen, dass "1" für "True" alleine nicht ausreicht. Daher können Sie "1" -Werte in boolesche Ausdrücke umwandeln, indem Sie testen, ob sie tatsächlich gleich "1" sind. Zum Beispiel:
%Vor%ist das Äquivalent zu dem, was Sie vorher hatten:
%Vor%Wenn Sie all dies zusammenfügen, sollten Sie einfach alle Instanzen reiner boolescher Werte des alten Codes in boolesche Ausdrücke in der Form "value = 1" übersetzen können, da eine 1 ein True erzeugt, 0 ein False , und NULL gibt Ihnen False.
JEDOCH besteht die wahre Komplexität darin, dass das Auswählen des Werts gegenüber dem Testen mit ihm über eine WHERE-Bedingung anders ist. Boolesche Ausdrücke werden in WHERE-Bedingungen korrekt ausgewertet, haben aber keine direkte Repräsentation für SELECT (besonders da NULL / Unknown nicht wirklich boolesch ist). Sie können also die "Value = 1" -Übersetzung in WHERE-Bedingungen verwenden, aber Sie benötigen weiterhin eine CASE-Anweisung, wenn Sie sie als Ergebnis AUSWÄHLEN möchten.
Wie bereits kurz erwähnt, ist NULL / Unknown nicht wirklich boolesch, es ist bedeutungslos zu versuchen, "NULL UND NULL" für eine WHERE-Bedingung in NULL zu konvertieren. Tatsächlich ist NULL wirklich FALSE, da es nicht als WAHR bestimmt werden kann. Auch dies kann für Ihre Zwecke in einer SELECT-Anweisung anders sein. Dies ist wiederum der Grund, warum die CASE-Anweisung dort Ihre einzige Wahl ist.
Tags und Links sql sql-server sql-server-2005 tsql