2010-11-19 9 views
1

Als ich dieser Ad-hoc-Abfrage in SQL Server versuchen (nehmen UserId ist ein NVARCHAR Feld):Wie funktioniert in diesem Fall das implizite Casting von SQL Server?

SELECT * FROM MyUser WHERE UserId = 123456 

ich diesen Fehler:

 
Msg 245, Level 16, State 1, Line 1 
Syntax error converting the nvarchar value 'foo' to a column of data type int. 

Offensichtlich gibt ein Wert ist 'foo' irgendwo auf meiner UserId Spalte.

Warum versucht SQL Server, meine gesamte Spalte in INTEGER zu konvertieren, anstatt das zu tun, was mir offensichtlich erscheint: meinen Suchwert in NVARCHAR umwandeln?

+0

Ich weiß nicht, warum es so ist.Aber das ist es, was es immer macht :) –

Antwort

3

Der Vergleich erfolgt mit den Regeln des Data Type Precedence:

When an operator combines two expressions of different data types, the rules for data type precedence specify that the data type with the lower precedence is converted to the data type with the higher precedence.

Die NVARCHAR Typ (Vorrang 25) umgewandelt int (Vorrang 16). Beachten Sie, dass die Priorität 1 "Höchste" bedeutet.

+0

+1 Genau das habe ich irgendwie in meinen eigenen Worten zu erklären versucht. Danke für diesen tollen Link! =) –

+0

Ich denke, dies ist etwas, das der Abfrageoptimierer handhaben sollte, bevor er die Abfrage an die Engine übergibt: Konvertiere meinen Suchwert in einen Typ, der funktionieren würde, gebe eine Warnung aus und lass mich damit durchkommen. Ah, gut. :-) – Tomalak

+0

@Tomalak: Vielleicht in einer zukünftigen Version von SQL Server! = P Hehehe ... –

2

Ich denke, das ist, weil es zwei Werte verschiedener Typen nicht vergleichen kann. Dann muss entweder Gleichheitsvergleichselemente in denselben Typ konvertiert werden. Hier ist int bevorzugt, denke ich.

Ich glaube, ein int einen Vorrang vor dem nvarchar Typ hat, also muss es versuchen implizit die nvarchar auf den int-Wert zu konvertieren.

EDIT # 1

"But wouldn't it be sensible to try and convert the value I have given to the type of the field I am searching in, instead of the other way around?"

Ja, das wäre schön, wenn es so wäre. Aber ich denke, das liegt daran, dass es zu viele Konversionsversuche geben würde, wenn man eine andere Art von Vergleich versucht.

where dateOfBirth = 1976-6-16 

vs

where dateOfBirth = N'1976-06-16' 

Im ersten Beispiel, was die Absicht des Benutzers? Soll überprüft werden, ob dateOfBirth dem Datumswert 1976-06-16 entspricht oder mit einem ganzzahligen Wert von 1976 - 6 - 16 verglichen wird, was zu 1954 führen würde, was vernünftig genug sein könnte, um es als das Jahr eines bestimmten Datums zu betrachten.

Ich denke, es gibt implizite Konvertierungen wie nvarchar zu datetime, aber es würde viel zu decken, so dass sie sich auf die am häufigsten mögliche Konvertierung beschränkt.

+0

Aber wäre es nicht vernünftig zu versuchen, den Wert zu konvertieren, den ich dem Typ des Feldes gegeben habe, in dem ich suche, anstatt umgekehrt? – Tomalak

+1

Ja. Es ist ärgerlich, weil es den Index dabei bewusst zu vermeiden scheint - selbst wenn Sie einen Primärschlüssel auf UserID haben und nach einem in der Tabelle suchen, können Sie das Ergebnis zwar finden, aber Sie werden auch den Fehler (dh Sie erhalten eine Ergebniszeile, die _as well_ als Fehler aus einer anderen Zeile zurückgegeben wird, die nicht übereinstimmt.) Oracle tut dies auch, und ich habe nie viel Sinn darin gesehen; Ich denke, es ist nur ein Nebeneffekt der standardmäßigen Promotion/Conversion-Regeln. –

+0

Die Absicht von 'where dateOfBirth = 1976-6-16 'ist eindeutig das arithmetische Ergebnis von' 1976 - 6 - 16 '. DATETIME ist ein numerischer Typ, der Benutzer gab eine numerische Eingabe (ein Ausdruck, aber nichtsdestoweniger). Wenn ich ihm einen String gebe ('N'1976-06-16''), konvertiert der Server * offensichtlich * ihn vor der Verwendung in DATETIME, sonst würden diese Abfragen nicht funktionieren. Es könnte also schlau genug sein, das Gleiche in der in meiner Frage beschriebenen Situation zu tun. ;-) Aber ich weiß es zu schätzen, dass die Dinge so sind, wie sie sind. – Tomalak

1

Warum geben Sie einen Ganzzahlwert an, wenn Sie wissen, dass die Spalte NVARCHAR ist?

Leider ist SQL Server, wie viele SQL-Implementierungen, in seiner Typunterstützung weit hinter anderen Sprachen zurück. Die Typprüfung wird normalerweise nur zur Laufzeit durchgeführt. Daher werden Suchanfragen wie Ihre nicht durch Syntax überprüft, um Probleme wie die hier angesprochene hervorzuheben. Ihre Abfrage ist fehlerhaft, da Sie unterschiedliche Typen nicht zuordnen können. Da SQL Server diese Daten jedoch nicht verwendet, sind die Ergebnisse abhängig von den Daten nicht vorhersehbar.

+0

Warum? Weil es sich um eine Ad-hoc-Abfrage handelte und ich nicht daran dachte, die Zitate diesmal zu tippen. Ich war nur überrascht von der immensen Dummheit der Fehlermeldung und fragte mich, ob es eine tiefere Begründung dafür gab. Es stellt sich heraus, es ist nicht - es ist "nur so". – Tomalak

+0

@Tomalak: Eine viel bessere Fehlermeldung wäre "type mismatch" - aber die Auflösung wäre immer noch die gleiche: beheben Sie Ihre Abfrage, um den richtigen Werttyp anzugeben. – sqlvogel

+0

Ich wollte nicht sagen, der * Wortlaut der Nachricht * war dumm, ich sage die Art, wie SQL Server * die Situation behandelt * ist dumm. ;-) – Tomalak