שאילתות וטעינת נתונים לטבלה
לאחר שיצרת או קיבלת אובייקט טבלה בתסריט, השלב הבא הוא טעינת נתונים לתוכה.טעינת נתונים בהייפר אינה מתבצעת באמצעות SQL, אלא באמצעות רכיב תקשורת למסד הנתונים מסוג ThDB_Client.
בדרך כלל תראה אותו בקוד בשם Server או DBconn, בהתאם למודול שממנו נפתח עורך התסריטים.
המנגנון עובד בשיטה של בניית פקודות בזיכרון ושליחתן לשרת בפעימה אחת:
- Reset - התחלת סט פקודות חדש.
- Load או Query - הגדרת פעולת טעינה.
- Where - הוספת תנאי סינון, כאשר מדובר בשאילתה.
- Close_Query - סגירת הגדרת השאילתה.
- Execute - שליחת כל הפקודות לשרת וביצוע בפועל.
בעמוד זה נבנה את ההבנה בהדרגה:
תחילה נבחין בין ניקוי טבלה מקומית, בחירת מאגר אחסון, טעינת רשומה בודדת, ושאילתה לפי תנאים.
לאחר מכן יוצגו דוגמאות קוד מלאות לפי סדר העבודה בפועל.
הערות:
- בדוגמאות בעמוד זה נעשה שימוש בשם Server. אם במודול שלך רכיב מסד הנתונים נקרא DBconn, השימוש זהה.
- לפני כתיבת שאילתה, ודא שאתה מכיר את שם הטבלה, שדות המפתח, סוגי השדות וקשרי הטבלה לטבלאות אחרות.
-
משמעות ערך השורה -1בגישה לנתוני טבלה היא גישה לשורה הפעילה הנוכחית של הטבלה.
Clear - ניקוי הטבלה המקומית
הפקודה Clear מנקה את תוכן הטבלה המקומית בזיכרון.היא אינה מוחקת רשומות ממסד הנתונים, אינה שולחת פקודה לשרת, ואינה משנה את מבנה השדות של הטבלה.
השימוש העיקרי ב־Clear הוא לוודא שאין בטבלה נתונים ישנים לפני טעינה חדשה, או להכין טבלת עבודה ריקה.
| קוד | הסבר יישום |
|---|---|
| ServTicket.Clear; |
ניקוי כל הרשומות הקיימות כרגע באובייקט הטבלה ServTicket.
הפקודה משפיעה רק על הזיכרון המקומי של התסריט או המסך. |
| Server.Reset; |
ניקוי סט הפקודות שנבנה מול שרת הנתונים.
זוהי לא פקודת ניקוי לטבלה, אלא התחלה של טרנזקציה/בקשה חדשה מול השרת. |
| Server.Query(ServTicket, True, '', 'N'); |
פתיחת שאילתה על הטבלה ServTicket.
הפרמטר True אומר למנגנון לנקות את הטבלה לפני הכנסת תוצאות השאילתה החדשה. |
| Server.Query(ServTicket, False, '', 'N'); |
פתיחת שאילתה ללא בקשת ניקוי אוטומטי של הטבלה לפני התוצאה.
השתמש באפשרות זו רק כאשר אתה יודע שאתה רוצה לשמר את הנתונים שכבר נמצאים בטבלה. |
מתי מומלץ להריץ Clear ידנית
- לפני Load כאשר הטבלה כבר מכילה רשומה קודמת, ואתה לא רוצה להציג נתונים ישנים במקרה שהטעינה החדשה לא מצאה רשומה.
- לפני מילוי ידני של ThPrvTable המשמשת כטבלת עבודה זמנית.
- לפני Query שבו בחרת להשתמש בפרמטר False, ורק אם אתה רוצה לנקות בעצמך לפני השאילתה.
דוגמאות מלאות שמשלבות Clear עם Load או Query יופיעו בפרקים הבאים, לאחר שהפקודות עצמן יוסברו.
מאגרי האחסון של הטבלאות במסד הנתונים - N / A / D
לפני שנלמד כיצד לבצע שימוש ב־Load או Query חשוב להבין כי לכל טבלה בהייפר קיימים שלושה מאגרי אחסון לוגיים.המאגר שממנו טוענים נתונים נקבע באמצעות הפרמטר Attrib, שמופיע בפקודות רבות של Server/DBconn:
כגון: Load, Query, Save, Delete, Update ועוד.
בקריאות Load ו־Query יש לציין תמיד את מאגר האחסון במפורש.
עם זאת, מאחר שהפרמטר Attrib מוגדר כמחרוזת, ניתן לבצע חיפוש וטעינה ממספר מאגרים יחד, לדוגמה 'NA'.
כל אות במחרוזת מייצגת מאגר אחר שהשרת צריך לכלול בפעולת הטעינה או השאילתה.
| Attrib | שם המאגר | הסבר יישום |
|---|---|---|
| 'N' | Normal |
המאגר הפעיל והעכשווי של הטבלה.
זהו המאגר שבו משתמשים כמעט בכל טעינה, חיפוש, עריכה ועבודה יומיומית מול נתונים. |
| 'A' | Archive |
מאגר ארכיון לרשומות תקינות שאינן נדרשות בדרך כלל לשימוש יומיומי.
העברת רשומות לארכיון יכולה להתבצע ידנית או אוטומטית, בהתאם ללוגיקה של המודול. מטרת הארכיון היא לצמצם את כמות הרשומות במאגר N, ובכך להאיץ חיפוש וטעינה של נתונים פעילים. |
| 'D' | Deleted |
מאגר רשומות מחוקות.
רשומות יכולות לעבור אליו בעקבות מחיקה ידנית של משתמש או מחיקה/העברה שבוצעה על ידי המערכת. בדרך כלל לא עובדים מול מאגר זה במסכי עבודה רגילים, אלא לצורכי בדיקה, שחזור, בקרה או מנגנונים פנימיים. |
| 'NA' | Normal + Archive |
טעינה משולבת מהמאגר הפעיל ומהארכיון.
שימושי במיוחד לדוחות, חיפושים היסטוריים, או מסכים שבהם המשתמש צריך לראות גם מידע שוטף וגם מידע ישן שהועבר לארכיון. |
| 'NAD' | Normal + Archive + Deleted |
טעינה מכל שלושת המאגרים.
שימוש כזה צריך להיות חריג ומודע, בדרך כלל לצורכי בקרה, בדיקה, שחזור או כלים ניהוליים. |
למה זה חשוב לשאילתות?
- Load או Query צריכים לקבל פרמטר Attrib מפורש. בעבודה רגילה נשתמש בדרך כלל ב־'N'.
- אם רשומה הועברה לארכיון, חיפוש רגיל במאגר N לא ימצא אותה.
-
כאשר בונים דוח היסטורי, ניתן לטעון ממאגר A בלבד או לשלב מאגרים באמצעות Attrib = 'NA'.
- שאילתה למאגר D צריכה להיות פעולה מודעת וזהירה, כי מדובר ברשומות שנחשבות מחוקות מבחינת העבודה השוטפת.
דוגמאות קוד שמשתמשות ב־Attrib יופיעו בהמשך, בפרקים של Load ו־Query.
בשלב זה מספיק להבין כי בחירת המאגר היא חלק מהפקודה שטוענת את הנתונים, ולא פעולה נפרדת.
Load - טעינת רשומה לפי מפתח
הפקודה Load מיועדת לטעינת רשומה אחת לפי מפתח ראשי.לדוגמה: טעינת לקוח לפי מספר לקוח, טעינת קריאת שירות לפי מספר קריאה, או טעינת מסמך לפי מספר מסמך.
אם אתה נדרש לחפש ולטעון רשומה מלאה ובדדה, הפרוצדורה Load עדיפה על Query מתוקף היותה מהירה יותר!
קוד הפקודה:
Server.Load(HTable: ThTable; PrimaryKey: Variant; Attrib: String); // Variant יכול להיות מספר או מחרוזת
| פרמטר | הסבר יישום |
|---|---|
| HTable | אובייקט הטבלה שאליו ייטענו הנתונים. |
| PrimaryKey |
ערך המפתח הראשי של הרשומה לטעינה.
יכול להיות מספרי או מחרוזת, בהתאם לסוג שדה המפתח בטבלה. |
| Attrib | מצביע למקום האחסון במסד הנתונים. |
דוגמאות Load לפי מאגר אחסון
טעינה רגילה מהמאגר הפעיל:ServTicket.Clear;
Server.Reset;
Server.Load(ServTicket, Ticket_Number, 'N');
IF NOT Server.Execute Then EXIT;
טעינה כאשר הרשומה עשויה להימצא במאגר הפעיל או בארכיון:
ServTicket.Clear;
Server.Reset;
Server.Load(ServTicket, Ticket_Number, 'NA');
IF NOT Server.Execute Then EXIT;
טעינת רשומה מהארכיון:
ServTicket.Clear;
Server.Reset;
Server.Load(ServTicket, Ticket_Number, 'A');
IF NOT Server.Execute Then EXIT;
בדוגמאות Load מומלץ לנקות את הטבלה לפני הטעינה, כדי שלא יוצגו נתונים ישנים במקרה שהרשומה המבוקשת לא נמצאה.
דוגמה לטעינת קריאת שירות לפי מספר קריאה:
Procedure LoadServiceTicket(Ticket_Number: Integer);
VAR ServTicket: ThTable;
Begin
ServTicket:= Fman.Find_Table('ServTicket');
ServTicket.Clear;
Server.Reset;
Server.Load(ServTicket, Ticket_Number, 'N');
IF NOT Server.Execute Then EXIT;
IF ServTicket.Empty Then
PopupMessage('Service ticket was not found.');
End;
טעינת כמה טבלאות באותה פעימה:
Server.Reset;
Server.Load(ClientTb, Client_Number, 'N');
Server.Load(ContactsTb, Client_Number, 'N');
Server.Load(Record_ExtnsionTb, Client_Number, 'N');
IF NOT Server.Execute Then EXIT;
טעינה מרוכזת כזו עדיפה על שליחה נפרדת של כמה בקשות לשרת, כאשר כל הנתונים דרושים לאותה פעולה.
Query - שאילתה לפי תנאים
הפקודה Query מיועדת לטעינת רשומות לפי תנאי סינון.בניגוד ל־Load, שאילתה יכולה להחזיר אפס רשומות, רשומה אחת או הרבה רשומות.
קוד הפקודה:
Server.Query(HTable: ThTable; Clear_On_Init: Boolean; Remember_Nickname: String; Attrib: String);
| פרמטר | הסבר יישום |
|---|---|
| HTable | הטבלה שאליה ייטענו תוצאות השאילתה. |
| Clear_On_Init |
כאשר True, הטבלה תנוקה לפני טעינת תוצאות השאילתה.
ברוב השאילתות במסכים ובדוחות נשתמש ב־True. |
| Remember_Nickname |
שם זמני עבור מקבץ התוצאות לטובת שימוש בשאילתה עוקבת (מוסבר לעומק בעמוד ההדרכה הבא).
בעבודה בסיסית יש להעביר מחרוזת ריקה. |
| Attrib | מצביע למקום האחסון במסד הנתונים. |
בעמוד זה נשתמש בדרך כלל במחרוזת ריקה בפרמטר Remember_Nickname.
השימוש בשם זיכרון לשאילתה, Query_And_Remember ושאילתות מקשרות מוסברים בעמוד ההמשך בנושא שאילתות מקשרות וזיכרון תוצאות.
שאילתות מול מאגרי אחסון
כאשר רוצים לקבוע באיזה מאגר לחפש, מעבירים את ערך Attrib בפרמטר הרביעי של Query.לדוגמה, שאילתה היסטורית מהארכיון בלבד:
Server.Reset;
Server.Query(ServTicket, True, '', 'A');
Server.Where_In_Range('Created On', From_Date, Until_Date + he_End_Of_Day, he_AND);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
כאשר נדרש לחפש גם במאגר הפעיל וגם בארכיון, ניתן להשתמש ב־'NA' באותה שאילתה:
Server.Reset;
Server.Query(ServTicket, True, '', 'NA');
Server.Where_SameVal('Entity Number', Client_Number, he_AND);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
שאילתה מול מאגר המחוקים צריכה להופיע רק כאשר יש צורך ברור בבדיקה, בקרה או שחזור:
Server.Reset;
Server.Query(DeletedTickets, True, '', 'D');
Server.Where_SameVal('Entity Number', Client_Number, he_AND);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
שים לב: אם אותה שאילתה צריכה לחפש בכמה מאגרים, עדיף להשתמש ב־Attrib משולב כמו 'NA', במקום להריץ שתי שאילתות נפרדות לאותה טבלה.
פקודות Where נפוצות
פקודות Where מגדירות את תנאי הסינון של השאילתה.כל פקודת Where מקבלת בדרך כלל שם שדה, ערך להשוואה, וקבוע לוגי כגון he_AND או he_OR.
| פקודה | מתי משתמשים |
|---|---|
| Where_SameVal |
כאשר צריך התאמה מדויקת לערך מספרי או טקסטואלי.
|
| Where_Above |
כאשר ערך השדה צריך להיות גדול או שווה לערך שנמסר. כלומר: >=.
|
| Where_Below |
כאשר ערך השדה צריך להיות קטן או שווה לערך שנמסר. כלומר: <=.
בתאריכים, ניתן להוסיף he_End_Of_Day כדי לכלול את סוף היום.
|
| Where_In_Range |
כאשר ערך השדה צריך להיות בטווח כולל בין מינימום למקסימום.
|
| Where_String_Search |
חיפוש טקסטואלי עם תמיכה בתו * לחיפוש חלקי.
|
| Where_Contain_String |
בדיקה אם טקסט מסוים מופיע בתוך שדה טקסט.
|
| Where_Date_In_Period |
סינון לפי ביטוי תקופה טקסטואלי, לדוגמה שנה, חודש או טווח חודשים.
|
| Where_Cont_Group_Items |
בדיקה אם שדה המכיל רשימת פריטים כולל אחד מהפריטים שנמסרו.
|
| Where_Compare_Between |
השוואה בין שני שדות באותה רשומה.
|
LogicGate - חיבור תנאי Where
כל פקודת Where מקבלת בסוף פרמטר בשם LogicGate מסוג Thds_Logic.פרמטר זה קובע איך התנאי הנוכחי מתחבר לתנאים שכבר הוגדרו באותה שאילתה.
בתסריטים יש להעביר את הפרמטר הזה במפורש בכל קריאת Where.
גם כאשר הכוונה היא לחיבור רגיל מסוג AND, יש לכתוב he_AND כפרמטר האחרון בכל פקודת Where.
Thds_Logic = (he_AND, he_OR, he_AND_NOT, he_OR_NOT);
| קבוע | משמעות בשאילתה |
|---|---|
| he_AND |
התנאי הנוכחי חייב להתקיים בנוסף לתנאים הקודמים.
זהו הערך הרגיל והנפוץ ביותר. |
| he_OR | התנאי הנוכחי יכול להתקיים כחלופה לתנאי קודם באותה קבוצת תנאים. |
| he_AND_NOT |
התנאי הנוכחי חייב שלא להתקיים, בנוסף לשאר התנאים.
שימושי כאשר רוצים להוציא ערך מסוים מתוך תוצאה רחבה יותר. |
| he_OR_NOT |
חלופה לוגית שלילית. שימושית רק במקרים שבהם צריך לצרף תנאי מסוג OR על אי־התאמה.
ברוב התסריטים עדיף להימנע ממנה אלא אם מבנה השאילתה ברור מאוד. |
דוגמה רגילה עם כמה תנאים שחייבים להתקיים יחד:
Server.Reset;
Server.Query(ServTicket, True, '', 'N');
Server.Where_SameVal('Entity Number', Client_Number, he_AND);
Server.Where_SameVal('Ticket Status', 1, he_AND);
Server.Where_Above('Created On', From_Date, he_AND);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
שים לב: אין להשמיט את הפרמטר LogicGate מהדוגמאות ומהתסריטים.
קריאת Where ללא LogicGate אינה תבנית כתיבה תקינה עבור מדריך זה.
כמה ערכים לאותו שדה
כאשר קוראים ל־Where_SameVal כמה פעמים ברצף על אותו שדה, המערכת מוסיפה את הערכים לאותו תנאי שדה.
לכן זו הדרך הנכונה לחפש רשומות שבהן אותו שדה יכול להיות אחד מכמה ערכים:
Server.Reset;
Server.Query(ServTicket, True, '', 'N');
Server.Where_SameVal('Ticket Status', 0, he_AND);
Server.Where_SameVal('Ticket Status', 1, he_AND);
Server.Where_SameVal('Ticket Status', 2, he_AND);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
בדוגמה זו נטענות רשומות שבהן Ticket Status הוא 0 או 1 או 2.
אין צורך להשתמש ב־he_OR כאשר מדובר באותו שדה ובאותה פקודת Where_SameVal.
שילוב OR בין שדות שונים
כאשר החלופה היא בין שדות שונים, יש להשתמש ב־he_OR.
לדוגמה, חיפוש טקסט בנושא הקריאה או בהערות הפנימיות:
Server.Reset;
Server.Query(ServTicket, True, '', 'N');
Server.Where_Contain_String('Subject / Complain', SearchText, he_OR);
Server.Where_Contain_String('Internal Notes', SearchText, he_OR);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
קבוצות תנאים
כאשר רוצים לחבר כמה קבוצות תנאים, משתמשים ב־Close_Group_And_Start_A_New_Group.
הפקודה סוגרת את קבוצת התנאים הנוכחית ופותחת קבוצה חדשה, כאשר הפרמטר שלה קובע איך הקבוצה החדשה מתחברת לקבוצה הקודמת.
לפי המימוש בקוד, אם עדיין לא הוגדר תנאי Where קודם, הקריאה לפקודה לא תיצור קבוצה חדשה.
Server.Reset;
Server.Query(ServTicket, True, '', 'N');
Server.Where_SameVal('Entity Number', Client_Number, he_AND);
Server.Close_Group_And_Start_A_New_Group(he_AND); // סגירת קבוצת תנאים קודמת
Server.Where_Contain_String('Subject / Complain', SearchText, he_OR);
Server.Where_Contain_String('Internal Notes', SearchText, he_OR);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
בדוגמה זו הקבוצה הראשונה מסננת לפי הלקוח, והקבוצה השנייה מחפשת את הטקסט באחד משני שדות.
התוצאה הלוגית היא: לקוח מסוים, וגם התאמה באחד משדות הטקסט.
שלילת תנאים
כאשר רוצים להוציא ערך מסוים מתוך התוצאה, משתמשים בדרך כלל ב־he_AND_NOT:
Server.Reset;
Server.Query(ServTicket, True, '', 'N');
Server.Where_SameVal('Entity Number', Client_Number, he_AND);
Server.Where_SameVal('Ticket Status', 9, he_AND_NOT);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
בדוגמה זו נטענות קריאות של הלקוח, למעט קריאות שבהן Ticket Status שווה 9.
Close_Query ו־Execute
לאחר שסיימת להגדיר את כל תנאי השאילתה, יש לסגור אותה באמצעות Close_Query.רק לאחר מכן מריצים Execute, ששולח את כל הפקודות שנבנו לשרת.
| קוד | הסבר יישום |
|---|---|
| Server.Close_Query; |
סוגר את הגדרת השאילתה הנוכחית.
חובה להריץ לאחר שסיימת להוסיף תנאי Where לשאילתה. |
| Server.Execute; |
מבצע בפועל את כל הפקודות שנבנו מאז Server.Reset.
הפונקציה מחזירה Boolean, ולכן מומלץ לבדוק את התוצאה לפני המשך עבודה. |
תבנית עבודה מומלצת:
Server.Reset;
Server.Query(ServTicket, True, '', 'N');
Server.Where_SameVal('Entity Number', ClientTb.IField['Client Number',0], he_AND);
Server.Close_Query;
IF NOT Server.Execute Then
Begin
Fman.SB_Message('Failed to load service tickets.', True);
EXIT;
End;
שילוב כמה שאילתות בבקשה אחת
ניתן לבנות כמה פעולות טעינה ושאילתה לאחר Reset אחד, ולבצע את כולן ב־Execute אחד.שיטה זו שימושית כאשר המסך צריך לטעון כמה טבלאות יחד.
Server.Reset;
Server.Load(ClientTb, Client_Number, 'N');
Server.Query(ServTicket, True, '', 'N');
Server.Where_SameVal('Entity Number', Client_Number, he_AND);
Server.Close_Query;
Server.Query(ContactsTb, True, '', 'N');
Server.Where_SameVal('Entity Number', Client_Number, he_AND);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
שים לב: לכל Query יש להריץ Close_Query משלה לפני מעבר לשאילתה הבאה או לפני Execute.
בדיקת תוצאה לאחר טעינה
לאחר Execute מוצלח, הנתונים נמצאים בתוך אובייקט הטבלה.כדי לבדוק אם נטענו רשומות, ניתן להשתמש במספר כלים המוסברים להלן:
| קוד | הסבר יישום |
|---|---|
| TableName.Empty(0) |
בדיקה באם קיים תוכן בשדה 0 (הטור הראשון)
באפשרותך לבצע את הבדיקה על כל מספר טור שתבחר אך נהוג להריץ על טור המפתח. מחזיר True כאשר לא נמצא נתון בטור הנבחר. |
| TableName.RowCount |
מחזיר את מספר הרשומות הקיימות בטבלה.
הבעיה בבדיקה זו היא שטבלה ריקה תחזיק ברשומה אחת (רשומה מס 0) ריקה מערכים. קח זאת בחשבון! |
| TableName.Row | השורה הפעילה הנוכחית בטבלה. |
דוגמה:
IF ServTicket.Empty(0) Then
Begin
Fman.SB_Message('No service tickets were found.', True);
EXIT;
End;
Fman.SB_Message(IntToStr(ServTicket.RowCount) + ' service tickets were loaded.', False);
טעויות נפוצות
| טעות | הסבר ותיקון |
|---|---|
| שכחת Server.Reset | Reset מתחיל סט פקודות חדש. בלי Reset אתה עלול לעבוד על פקודות שנשארו מבנייה קודמת. |
| שכחת Close_Query | כל Query עם תנאי Where צריך להיסגר באמצעות Close_Query לפני Execute או לפני Query נוסף. |
| שימוש ב־Load במקום Query |
Load מתאים לרשומה אחת לפי מפתח ראשי.
כאשר צריך לחפש לפי שדה שאינו מפתח, או לקבל כמה רשומות, השתמש ב־Query. |
| שימוש בטקסט עבור שדה Status | בשדות סטטוס מומלץ לעבוד לפי הערך המספרי של הפריט ברשימה, ולא לפי הטקסט המתורגם שמוצג למשתמש. |
| השארת נתונים ישנים בטבלה | כאשר טבלה משמשת לטעינות חוזרות, השתמש ב־Clear או ב־Query עם Clear_On_Init=True כדי להימנע מתצוגת נתונים ישנים. |
תבניות קוד קצרות
טעינת רשומה אחת:TargetTb.Clear;
Server.Reset;
Server.Load(TargetTb, Record_Key, 'N');
IF NOT Server.Execute Then EXIT;
שאילתה פשוטה:
Server.Reset;
Server.Query(TargetTb, True, '', 'N');
Server.Where_SameVal('Field Name', Value, he_AND);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
שאילתה לפי טווח תאריכים:
Server.Reset;
Server.Query(TargetTb, True, '', 'N');
Server.Where_In_Range('Created On', From_Date, Until_Date + he_End_Of_Day, he_AND);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;
שאילתה במאגר הפעיל ובארכיון:
Server.Reset;
Server.Query(TargetTb, True, '', 'NA');
Server.Where_SameVal('Field Name', Value, he_AND);
Server.Close_Query;
IF NOT Server.Execute Then EXIT;