2016-05-03 15 views
0

Ich habe einen indizierte (aber nicht eindeutig) varchar Bereich des Mitarbeiter-IDs in einer Tabelle aufgestellt, und in einer Abfrage muß ich Zeilen zurückgeben, die exactly 4 numerical characters sind, sondern auch über 1000Warum sollte ich "zwischen X und Y" in einem Varchar-Feld in SQL nicht verwenden, um eine Zahl zurückzugeben?

Ich habe auf verschiedene Fragen gefunden hier über die Verwendung von Validierungsmethoden, um zu überprüfen, ob das Feld 0-9 Zeichen enthält oder keine az-Zeichen usw. enthält, die jedoch nicht mit dieser Frage in Zusammenhang stehen.

Hintergrund:

ich eine Tabelle mit verschiedenen Werten haben, setzen Probe wie folgt:

EmployeeID 
---------- 
6745 
EMP1 
EMP2 
1874 
LTST 
5694 
0014 

Was würde ich alle Werte außerEMP1, zu tun ist Rückkehr EMP2 , LTST und .

Meine Frage ist, gibt es irgendwelche Gründe, warum ich nicht eine Where-Klausel wie where EmployeeID between '1000' and '9999' verwenden sollte? Der Grund dafür, dass employewid ist eine Varchar-Spalte

Wenn ich das tun kann, sollte ich auch nach Mitarbeiter-ID bestellen, oder spielt das keine Rolle?

+0

Rückkehr alle Werte außer EMP1, EMP2, LTST und 0014. Was für dies ist der Grund .you ein tun zwischen genauso, wie Sie in Frage gestellt haben. Was ist das Problem, das Sie konfrontiert sind – TheGameiswar

+0

@TheGameiswar meine Frage ist, ob es Gründe gibt, dass ich nicht 'zwischen' auf diese Weise verwenden sollte, dh konnte es unerwartete Ergebnisse zurückgeben, die nicht numerisch sind wir lesen sie – laurencemadill

Antwort

1

Führen Sie den folgenden Code als ein Beispiel und Sie werden feststellen, dass SQL Server nicht sehen INT die gleiche wie ganze Zahlen wie VARCHAR gespeichert ist behandeln:

WITH IntsAsVars 
AS  (
     SELECT var = '1000', 
       int = 1000 
     UNION ALL 
     SELECT var = '100', 
       int = 100 
     UNION ALL 
     SELECT var = '9999', 
       int = 999 
     UNION ALL 
     SELECT var = '99', 
       int = 99 
     UNION ALL 
     SELECT var = '750', 
       int = 750 
     UNION ALL 
     SELECT var = '10', 
       int = 10 
     UNION ALL 
     SELECT var = '2', 
       int = 2 
     ) 
SELECT * 
FROM IntsAsVars 
--WHERE var BETWEEN '2' AND '750' 
/* should return 2, 10, 99, 100 & 750 if it works like INT 
    but does it? */ 
ORDER BY 
     --var ASC, 
     int ASC; 

es läuft, ohne die where-Klausel die folgenden so erhält SQL Server nicht die anderen Datensätze prüfen zwischen 2 und 750 sein, wenn sie als varchar gespeichert sind .:

enter image description here

+0

Danke für die Antwort. Mein Szenario würde dieses Problem nicht sehen, weil ich mich auch mit Zeichen fester Länge beschäftige. – laurencemadill

+0

Das ist fair, aber hört das Werte wie "0001" auf? "0011"? etc? – Shaneis

2

ich glaube, „0014“ verlassen würde aus dem wo clau se , das ist ein Grund. Vielleicht würde between '0000' and '9999' Ihren Zwecken besser entsprechen. Denken Sie daran, dass Sie immer noch basierend auf Text sortieren. Wenn Sie Einträge wie "1_99" haben, würde dies auch in Ihren Abfrageergebnissen mit Ihrer gegebenen between-Klausel angezeigt werden.

Wenn Sie schauen, nur 4-stellige Zahlen zurückzukehren ohne führende Nullen, dann sollte die folgende Zugabe genügen:

WHERE EmployeeID BETWEEN '1000' AND '9999' AND TRY_CAST(EmployeeID As int) IS NOT NULL 

... oder, intuitiv:

WHERE TRY_CAST(EmployeeID As int) BETWEEN 1000 AND 9999 
+0

Ja, ich möchte, dass "0014" weggelassen wird. In diesem Fall möchte ich nur Varchar-Werte, die tatsächlich numerisch sind, und tatsächlich 4 Zeichen sind, wobei führende Nullen ausgeschlossen sind. Es sind die Werte wie '1_99', um die ich mich sorgen würde – laurencemadill

1

Wenn Ihre realen Daten sind genauso wie die Beispieldaten in Bezug auf die nicht-numerischen Werte, die mit einem Buchstaben beginnen. Sie können Ihre Abfrage verwenden, um das gewünschte Ergebnis zu erzielen.

Beachten Sie jedoch die Sortierreihenfolge der Daten. Wenn Sie eine EmployeeId von 1ABC haben, wird diese in die von WHERE EmployeeID BETWEEN '1000' AND '9999' zurückgegebenen Daten aufgenommen!

Ihr Ansatz ist nicht geeignet, um nicht-numerische Werte herauszufiltern!

Eine zusätzliche ORDER BY wirkt sich nur auf die Reihenfolge der Ergebnisse aus, sie hat keinen Einfluss auf die Bewertung der WHERE-Bedingung.

0

Ich würde sagen, die einfachste Art und Weise, wie zu benutzen ist: Angenommen, Sie haben diesen Eingang lässt

select * from yourtable 
where EmployeeID like '[1-9][0-9][0-9][0-9]' 
0

:

IF OBJECT_ID('tempdb..#test') IS NOT NULL 
    DROP TABLE #test 

CREATE TABLE #test 
(
    EmployeeID VARCHAR(255) 
) 

CREATE CLUSTERED INDEX CIX_test_EmployeeID ON #test(EmployeeID) 

INSERT INTO #test 
VALUES 
('6745'), 
('EMP1'), 
('EMP2'), 
('1874'), 
('LTST'), 
('5694'), 
('1000'), 
('9999'), 
('10L'), 
('187'), 
('9X9'), 
('7est'), 
('1ok'), 
('0_o'), 
('0014'); 

Ihre Aussage würde auch zurückkehren '1OK', '187', '10L' und so weiter. Da Sie erwähnt, dass Ihr employeeID eine feste Länge hat, können Sie so etwas wie dies nutzen könnten:

SELECT * 
FROM #test 
WHERE EmployeeID LIKE '[1-9][0-9][0-9][0-9]'