{"id":616,"date":"2010-04-25T20:27:46","date_gmt":"2010-04-25T19:27:46","guid":{"rendered":"http:\/\/blog.m-ri.de\/?p=616"},"modified":"2010-04-25T16:55:51","modified_gmt":"2010-04-25T15:55:51","slug":"select-from-where-in-mystik","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2010\/04\/25\/select-from-where-in-mystik\/","title":{"rendered":"SELECT &#8230; FROM &#8230; WHERE &#8230; NOT IN (&#8230;) Mystik"},"content":{"rendered":"<p>Wieder mal ein ganz normaler Wahnsinn, der einen Stunden gekostet hat&#8230;<\/p>\n<p>Wenn wir uns die nachfolgenden SQL Statements ansehen, dann w\u00fcrde ich davon ausgehen, dass die ersten 6 eine Ausgabe erzeugen.<\/p>\n<pre lang=\"sql\">SELECT 'Test 1' WHERE 1 IN (NULL, 1, 2, 3, 4)\r\nSELECT 'Test 2' WHERE 1 IN (1, 2, 3, 4)\r\nSELECT 'Test 3' WHERE 1 NOT IN (NULL, 2, 3, 4) -- !!!\r\nSELECT 'Test 4' WHERE 1 NOT IN (2, 3, 4)\r\nSELECT 'Test 5' WHERE NOT (1 IN (NULL, 2, 3, 4)) -- !!!\r\nSELECT 'Test 6' WHERE NOT (1 IN (2, 3, 4))\r\n-- Empty as expected\r\nSELECT 'Test 5' WHERE 1 IN (NULL, 2, 3, 4)\r\nSELECT 'Test 6' WHERE 1 IN (2, 3, 4)<\/pre>\n<p>Aber \u2757 Pustekuchen \u2757<br \/>\n<strong>Die Zeilen 3 und\u00a05 erzeugen keine Ausgabe \u2757<strong><\/strong>Dadurch, dass in dem Ausdruck in der Klammer <em>NULL<\/em> enthalten ist funktioniert\u00a0der <em>NOT IN <\/em>Test nicht mehr korrekt.<\/strong><\/p>\n<p>Ich bin darauf gesto\u00dfen, weil ich ein Subquery durchgef\u00fchrthabe und mit <em>NOT IN <\/em>pr\u00fcfen wollte, dass ein bestimmter Wert eben nicht in diesem Subquery enthalten ist. Einziges Problem war, dass in einigen F\u00e4llen dieser Subquery eben auch <em>NULL<\/em> als Ergebnis geliefert hat.\u00a0<br \/>\nUnd genau in diesem Fall funktionierte die Abfrage nicht korrekt (s.o.). Das sah vereinfacht in etwas so aus:<\/p>\n<pre lang=\"sql\">SELECT [ID] FROM [Table1]\r\n\u00a0\u00a0\u00a0 WHERE [SomeData] NOT IN\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (SELECT [OtherIDWithNULL] FROM [Table2])<\/pre>\n<p>Ich habe den Subquery dann entsprechende um ein <em>WHERE &#8230; IS NOT NULL <\/em>erweitert und siehe da es ging:<\/p>\n<pre lang=\"sql\">SELECT [ID] FROM [Table1]\r\n\u00a0\u00a0\u00a0 WHERE [SomeData] NOT IN\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (SELECT [OtherIDWithNULL]\u00a0FROM [Table2]\r\n            WHERE [OtherIDWithNULL] IS NOT NULL)<\/pre>\n<p><strong>Rein gef\u00fchlt ist das f\u00fcr mich ein Bug,\u00a0aber es ist keiner \u2757<br \/>\n<\/strong>Hier kommt eine Einstellung zum tragen, die sich <em>ANSI_NULL <\/em>schimpft. (siehe <a href=\"http:\/\/msdn.microsoft.com\/de-de\/library\/ms188048.aspx\">SET ANSI_NULL { ON | OFF }<\/a>)<\/p>\n<p lang=\"sql\"><em>ANSI_NULL<\/em> ist im Allgemeinen <em>ON<\/em>, und das bedeutet, dass ein Vergleich eines Wertes mit <em>NULL <\/em>immer undefiniert ist. Das ein <em>IN<\/em>-Statement aber nichts anderes ist als ein Vergleich der einzelnen Werte in der Klammer mit dem Zielwert, f\u00fchrt dies hier zu einem irritierenden Ergebnis. <em>NULL=NULL<\/em> und <strong><em>1=NULL<\/em> ist eben undefiniert und nicht False<\/strong> wenn <em>ANSI_NULL ON<\/em> ist! Also k\u00f6nnen die Zeilen 3+5 kein korrektes Ergebnis liefern.<br \/>\nMan beachte: Dies hat keinen Einflu\u00df solange man <em>IN <\/em>verwendet und nicht <em>NOT IN<\/em>!<\/p>\n<p lang=\"sql\">Meine rein pers\u00f6nliche Meinung:<br \/>\nIch habe selten solch einen Unsinn in einem ANSI-Standard gesehen. Einfach Unlogisch \u2757<br \/>\nF\u00fcr mich ist <em>NULL=NULL<\/em> und <em>NULL&lt;&gt;AnyThingElse<\/em> eben <em>True<\/em>&#8230; Just my 2 cents&#8230;<\/p>\n<p lang=\"sql\">Jetzt k\u00f6nnte man meinen, dass es also auch eine L\u00f6sung w\u00e4re <em>SET_ANSI_NULL OFF<\/em> zu verwenden \u2757 (BTW: Eine Einstellung die\u00a0auch als Attribut direkt auf der Datenbank selbst gesetzt werden kann). Aber der folgende Hinweis in der Doku sollte einen zum Umdenken bewegen:<\/p>\n<blockquote><p>Wichtig:<br \/>\nIn einer sp\u00e4teren Version von SQL Server wird ANSI_NULLS immer auf ON festgelegt, und jede Anwendung, die f\u00fcr die Option explizit OFF festlegt, l\u00f6st einen Fehler aus. Verwenden Sie dieses Feature beim Entwickeln neuer Anwendungen nicht, und planen Sie eine \u00c4nderung von Anwendungen, in denen es zurzeit verwendet wird.<\/p><\/blockquote>\n<p>Da dies\u00a0also evtl. Einfluss auf andere Codebereiche haben k\u00f6nnte und zuk\u00fcnftig nicht mehr unterst\u00fctzt wird habe ich auf diese Nutzung verzichtet und lieber das Subquery abge\u00e4ndert.<\/p>\n<p lang=\"sql\">PS: Bitte jetzt nicht darauf hinweisen, dass es auch <em>JOIN<\/em> gibt. Aufgrund der Komplexit\u00e4t der Abfrage und weil diese auch noch nach bestimmten Bedingungen gebaut wurde, war ein <em>IN <\/em>mit einem Subquery, der einfachere Weg.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wieder mal ein ganz normaler Wahnsinn, der einen Stunden gekostet hat&#8230; Wenn wir uns die nachfolgenden SQL Statements ansehen, dann w\u00fcrde ich davon ausgehen, dass die ersten 6 eine Ausgabe erzeugen. SELECT &#8218;Test 1&#8216; WHERE 1 IN (NULL, 1, 2, 3, 4) SELECT &#8218;Test 2&#8216; WHERE 1 IN (1, 2, 3, 4) SELECT &#8218;Test 3&#8216; &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2010\/04\/25\/select-from-where-in-mystik\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eSELECT &#8230; FROM &#8230; WHERE &#8230; NOT IN (&#8230;) Mystik\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,9,15],"tags":[99,359],"class_list":["post-616","post","type-post","status-publish","format-standard","hentry","category-programmieren","category-sonstiges","category-sql","tag-bug","tag-sql"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/616","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/comments?post=616"}],"version-history":[{"count":1,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/616\/revisions"}],"predecessor-version":[{"id":618,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/616\/revisions\/618"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=616"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=616"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=616"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}