שאילתות וטעינת נתונים לטבלה

לאחר שיצרת או קיבלת אובייקט טבלה בתסריט, השלב הבא הוא טעינת נתונים לתוכה.
טעינת נתונים בהייפר אינה מתבצעת באמצעות 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 היא פעולה מקומית בלבד.
דוגמאות מלאות שמשלבות 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 כאשר צריך התאמה מדויקת לערך מספרי או טקסטואלי.
Server.Where_SameVal('Client Number', 1001, he_AND);
Where_Above כאשר ערך השדה צריך להיות גדול או שווה לערך שנמסר. כלומר: >=.
Server.Where_Above('Balance', 0, he_AND);
Where_Below כאשר ערך השדה צריך להיות קטן או שווה לערך שנמסר. כלומר: <=.
בתאריכים, ניתן להוסיף he_End_Of_Day כדי לכלול את סוף היום.
Server.Where_Below('Created On', Server.NOW + he_End_Of_Day, he_AND);
Where_In_Range כאשר ערך השדה צריך להיות בטווח כולל בין מינימום למקסימום.
Server.Where_In_Range('Created On', From_Date, Until_Date + he_End_Of_Day, he_AND);
Where_String_Search חיפוש טקסטואלי עם תמיכה בתו * לחיפוש חלקי.
Server.Where_String_Search('Client Full Name', 'Cohen*', he_AND);
Where_Contain_String בדיקה אם טקסט מסוים מופיע בתוך שדה טקסט.
Server.Where_Contain_String('Subject / Complain', 'urgent', he_AND);
Where_Date_In_Period סינון לפי ביטוי תקופה טקסטואלי, לדוגמה שנה, חודש או טווח חודשים.
Server.Where_Date_In_Period('Created On', '01/2026-03/2026', he_AND);
Where_Cont_Group_Items בדיקה אם שדה המכיל רשימת פריטים כולל אחד מהפריטים שנמסרו.
Server.Where_Cont_Group_Items('Authorized Groups', 'Admin,Managers', he_AND);
Where_Compare_Between השוואה בין שני שדות באותה רשומה.
Server.Where_Compare_Between('Actual Price', he_Less_Then, 'Cost Price', he_AND);

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;