הבלוג של גרי רשף

26/02/2010

חישוב ספרת ביקורת בתעודת הזהות

Filed under: Uncategorized — תגיות: — גרי רשף @ 17:35

ספרת הביקורת בתעודת הזהות מחושבת כך:
את הספרות במקומות האי-זוגיים החל מצד ימין כופלים ב-2 וסוכמים את הספרות (נניח אם מופיעה הספרה 8 – כופלים אותה ב-2 ומקבלים 16, וסכום הספרות הוא 7),
את הספרות במקומות הזוגיים כופלים ב-1 (כלומר- לוקחים אותן כמו שהן),
סוכמים את כל המכפלות,
והמשלים למספר העגול הבא (שמתחלק ב-10) הוא ספרת הביקורת.

נניח שתעודת הזהות היא 9148, אזי מימין לשמאל:
8*2=16 וסכום הספרות 7,
4*1=4,
1*2=2,
9*1=9.
נסכום את המכפלות: 7+4+2+9=22,
המשלים ל-30 הוא 8,
ולכן 8 היא ספרת הביקורת.

ספרת הביקורת נועדה לוודא שלא חלה טעות בהקלדת המספר:
אם עשינו טעות כמו השמטת ספרה, הקלדה של אותה ספרה פעמיים, או הקלדה של ספרה לא נכונה – ספרת הביקורת לא תתאים וכך נעלה על הטעות.
ברור שאם נעשה יותר מטעות אחת- יש סיכוי של 1:10 שהטעויות יקזזו זו את זו וספרת הביקורת תצא במקרה נכונה..
הפתרון לזה יכול להיות הקלדה כפולה של תעודת הזהות- בערך כמו שמקובל כשבוחרים סיסמה, אלא שהטרחה כאן גדולה – אם מקלידים מספר גדול של תעודות זהות, ועדיין יש סיכוי שנחזור פעמיים על אותה טעות.
ספרת הביקורת נותנת אם כך הגנה סבירה נגד טעויות נפוצות.

ולעצם העניין- לחישוב ספרת הביקורת ניתן לכתוב פונקציה מתאימה (UDF) אבל אני אעשה זאת באופן ישיר בשליפה עצמה.
אינני יודע אם זה יותר יותר יעיל או פחות יעיל, אבל יש לזה יתרון צנוע: לא צריך לרוץ אחר ה-DBA, למלא טופס בקשה בשלושה עותקים, ולהתחנן שיואיל בטובו להכניס לדטבייס את הפונקציה (שלא לדבר על תיקונים בעתיד)..
ניצור קודם כל טבלת נתונים:

Create Table T_Employees(TZ Varchar(10) Not Null Primary Key,Name Varchar(20));

Go

Insert Into T_Employees Values('330123123','Avi');

Insert Into T_Employees Values('5659824','Batya');

Insert Into T_Employees Values('65936224','Galit');

Insert Into T_Employees Values('45205957','Dan');

Insert Into T_Employees Values('571425','Hila');

Go

בגרסת 2008 ניתן לבצע את כל פעולות ה-Insert בפעם אחת,

אך מתוך התחשבות במשתמשי 2005 שאין ידם משגת- נכניס כל רשומה בנפרד..

וכעת לשליפה:

Select    TZ,

        Right(10-Right(Cast(Right(SUBSTRING(Reverse(TZ),1,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),1,1) As TinyInt)>=5 Then 1 Else 0 End+

            Cast(SUBSTRING(Reverse(TZ),2,1) As TinyInt)+

            Cast(Right(SUBSTRING(Reverse(TZ),3,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),3,1) As TinyInt)>=5 Then 1 Else 0 End+

            Cast(SUBSTRING(Reverse(TZ),4,1) As TinyInt)+

            Cast(Right(SUBSTRING(Reverse(TZ),5,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),5,1) As TinyInt)>=5 Then 1 Else 0 End+

            Cast(SUBSTRING(Reverse(TZ),6,1) As TinyInt)+

            Cast(Right(SUBSTRING(Reverse(TZ),7,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),7,1) As TinyInt)>=5 Then 1 Else 0 End+

            Cast(SUBSTRING(Reverse(TZ),8,1) As TinyInt)+

            Cast(Right(SUBSTRING(Reverse(TZ),9,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),9,1) As TinyInt)>=5 Then 1 Else 0 End+

            Cast(SUBSTRING(Reverse(TZ),10,1) As TinyInt),1),1) SB,

        Name

From    T_Employees;

כפי שאפשר לשים לב אני הופך את המחרוזת בעזרת הפונקציה Reverse וכך ניתן למנות את המקומות משמאל כמקובל,

ובכל שורה מטפל בספרה אחרת כאשר המקומות הריקים נחשבים ל-0.

השליפה נראית לא יעילה: ה-Reverse מחושב 15 פעמים לכל תעודת זהות, וחלק מהספרות נשלפות פעמיים בעזרת Substring;

אבל גם כשמנעתי זאת על ידי קינון שאילתות – היעילות מבחינת ה-Execution Plan לא השתנתה.

ליתר בטחון וכדי שלא יהיו לי נקיפות מצפון, הנה השליפה המקוננת:

Select    TZ,

        Right(10-Right(Cast(Right(TZ1*2,1) As TinyInt)+Case When TZ1>=5 Then 1 Else 0 End+

            TZ2+

            Cast(Right(TZ3*2,1) As TinyInt)+Case When TZ3>=5 Then 1 Else 0 End+

            TZ4+

            Cast(Right(TZ5*2,1) As TinyInt)+Case When TZ5>=5 Then 1 Else 0 End+

            TZ6+

            Cast(Right(TZ7*2,1) As TinyInt)+Case When TZ7>=5 Then 1 Else 0 End+

            TZ8+

            Cast(Right(TZ9*2,1) As TinyInt)+Case When TZ9>=5 Then 1 Else 0 End+

            TZ0,1),1) SB,

        Name

From    (Select    *,

                Cast(SUBSTRING(ZT,1,1) As TinyInt) TZ1,

                Cast(SUBSTRING(ZT,2,1) As TinyInt) TZ2,

                Cast(SUBSTRING(ZT,3,1) As TinyInt) TZ3,

                Cast(SUBSTRING(ZT,4,1) As TinyInt) TZ4,

                Cast(SUBSTRING(ZT,5,1) As TinyInt) TZ5,

                Cast(SUBSTRING(ZT,6,1) As TinyInt) TZ6,

                Cast(SUBSTRING(ZT,7,1) As TinyInt) TZ7,

                Cast(SUBSTRING(ZT,8,1) As TinyInt) TZ8,

                Cast(SUBSTRING(ZT,9,1) As TinyInt) TZ9,

                Cast(SUBSTRING(ZT,10,1) As TinyInt) TZ0

        From    (Select    *,

                        REVERSE(TZ) ZT

                From    T_Employees) T) T;

מודעות פרסומת

להגיב »

עדיין אין תגובות.

RSS feed for comments on this post. TrackBack URI

כתיבת תגובה

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

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s

בלוג בוורדפרס.קום.

%d בלוגרים אהבו את זה: