SQL SERVER CHECK NUMBER

  • פותח הנושא rnan
  • פורסם בתאריך

rnan

New member
SQL SERVER CHECK NUMBER

היי

מהי הדרך הטובה ביותר לבדוק האם ערך שלשהוא הוא מספר ( יכול להיות גם עשרוני)

ISNUMERIC הבנתי שלא מומלץ

תודה
 

גרי רשף

New member
בדקתי ב-SQL Server 2012 וזה נראה בסדר

אפשר להתווכח אם + הוא מספר (לטענת המערכת) או לא:
מצד אחד זה תו לא מספרי,
אבל מצד שני סימן פלוס לפני מספר זה דבר סביר ואם אין מספר אז זה אפס (בסימן פלוס)..

אם "שיקול דעתה" של הפונקציה אינו לטעמך אפשר בקלות לאלתר משהו.
אנסה בהמשך.
(Pitoach בטח יעשה זאת ב-CLR ואני אסתפק ב-TSQL).
 

pitoach

New member
למעשה זו באמת פונקציה מאוד בעייתית והדברים

ידועים כי זו אינה המטרה שלה.

למשל בדוק את התוצאות הבאות (או תסמוך על מה שאני רושם לך שתהיה התוצאה):

select ISNUMERIC('22'); -- 1
select ISNUMERIC('d'); -- 0
SELECT ISNUMERIC('1d8') -- 1
SELECT ISNUMERIC('1D8') -- 1
SELECT ISNUMERIC('1d') -- 0
SELECT ISNUMERIC('1D') -- 0

שים לב שנתון כמו 1D8 מחזיר תשובה חיובית.

ההסבר פשוט: הפונקציה הזו אינה בודקת אם מדובר במספר בכלל וזו לא המטרה שלה. זו פונקציה שבודקת האם אפשר לבצע CONVERT לנתון למספר, ואלו דברים שונים לחלוטין. CONVERT למספר אפשר לבצע גם לטורים מסוג כסף למשל ולכן סימנים כמו דולר או ש"ח או + ועוד מועברים בפונקציה הזו כחיוביים

למעשה כל הסוגים הבאים ניתן לבצע להם CONVERT ולכן כל התווים של סוגים אלו יחזירו ערך 1 (בסידור מתאים) :
numeric
bigint
money
smallint
smallmoney
tinyint
float
decimal
real

בוא עבור לתיקונים:
תיקון מהיר שתופס את רוב הפעולות הוא פשוט הוספה של סימון 'e0' בסיום. זה לא יבצע תיקון לכל הערכים שאינם מספר אבל יתקן את רוב הבעיות ולכן אם תריץ עתה את השאילתות שלנו תקבל תוצאה מתאימה יותר לשאלה "האם זה מספר":

select ISNUMERIC('22'+'e0'); -- 1
select ISNUMERIC('d'+'e0'); -- 0
SELECT ISNUMERIC('1d8'+'e0') -- 0
SELECT ISNUMERIC('1D8'+'e0') -- 0
SELECT ISNUMERIC('1d'+'e0') -- 0
SELECT ISNUMERIC('1D'+'e0') -- 0

* אתה יכול לעבוד ככה אבל אני שוב מזהיר שכרגע אני לא זוכר דוגמה אבל זה לא יעבוד תמיד.

כמו שכתב גרי הדרך הטובה ביותר היא שמוש ישיר בפונקציה קטנה של CLR או פשוט בבדיקה של תבנית מתאימה למספר (ביטוי רגולרי)
 

גרי רשף

New member
'1,234e0' מחזיר 0

אני מבין ש-e0 הוא חלק מייצוג מדעי ש"מחייב" את מה שלפניו להיות מספר דצימלי "רגיל".
 

pitoach

New member
משהו כזה
אבל כמו שאמרתי זה לא טוב לכל

מקרה ולכן תלוי בנתונים שלך.

אבל הדוגמה שלך לא טובה כי היא מחזירה 1 (בדקתי כרגע כדי להיות בטוח בשרת 2012)
SELECT ISNUMERIC('1.234'+'e0') -- 1

לרוב הנתונים זה עובד טוב. אם תמצאו נתון שלא יעבוד טוב שימו את הדוגמה בפורום
 

pitoach

New member
אני אעלה פונקציית CLR מחר לטובת מי שרוצה

* אם אזכור
 

pitoach

New member
שרתי SQL מגרסה 2005 עובדים עם פונקציות CLR

שמוכנסות לתוך מסד הנתונים והעבודה איתן אחר כך כמו כל פונקציה שאתה מגדיר במסד הנתונים
 

pitoach

New member
לא אני מתכוון ל DLL פנימי שמכניסים למסד עצמו

יש 3 שלבים בעקרון:
1. מייצרים DLL בעזרת כל שפת דוטנט ולכן הוא מתורגם ל CLR
2. מכניסים את ה DLL למסד הנתונים על ידי הגדרת פונקציית אסבלי:
CREATE ASSEMBLY SqlFunctions
FROM 'C:\MyCLR.dll'
WITH PERMISSION_SET = SAFE;
GO
3. מגידירם פונקציה שתעבוד עם האסבלי הזה שהוא כרגע כבר פנימי ואפשר למחוק את הקובץ החיצוני:
CREATE FUNCTION MyFunction([input parametres u can put here])
RETURNS [type u return like int]
AS EXTERNAL NAME SqlFunctions.[SqlFunctions.DataTypeTests].MyFunction
GO

משהו כזה
 

rnan

New member
PITOACH , זה בדיוק מה שרשמתי

חייבים לעשות ENABLE CLR בהתחלה או משהו כזה.

עשיתי את זה בזמנו עם ספריות REGEX.
 

pitoach

New member
אבל שאלת אם זה שימוש ב DLL חיצוני וזה לא

ניתן גם לעבוד עם DLL חיצוני בלי להכניס למסד הנתונים אבל זה משהו אחר


בכל מקרה כניראה התכוונת לאותו דבר וזה העיקר

* לא רק שזה ייתן פתרון יותר טוב לצורך של בדיקה "האם זה מספר" (תלוי בקוד שאני אכתוב) זה גם ייתן תוצאות הרבה יותר יעילות על הדרך והרבה יותר מהר ככל הנראה.
 

rnan

New member
כל הכבוד על הפוסט

אני רק מקווה שיהו כאלה על אינדקסים ( נושא חשוב בעיניי)
 

rnan

New member
כל ה 2012 והבלאגן - ולא שמו שם פונקציה מוכנה?

 
למעלה