T-SQL BASIC

שפת Transact-SQL היא שפה פרוצדורלית שמרחיבה את שפת SQL ומאפשרת שימוש במשתנים, פונקציות, תנאים, לולאות וכו'

מושגי יסוד

  • Batch – אוסף פקודות שנשלחות לשרת יחד.
  • GO – מפריד בין Batch ל-Batch.
  • [] – לשימוש עם מילים שמורות או שמות עם רווחים.
  • @ – סימון למשתנה.
  • #- סימון למשתנה זמני, מקומי.
  • ##- סימון למשתנה זמני, גלובלי.

הגדרת משתנים מקומיים – Local Variables

משתנים מקומיים מוגדרים בתוך משפט SQL או פרוצדורה עם מילת המפתח DECLARE. משתנה מקומי מחזק ערך אחד בךבד.

DECLARE @local_variable data_type [,@local_variable data_type,…]

דוגמא:

DECLARE @CustomerID CHAR(5)
DECLARE @CustomerID CHAR(5), @CustomerName VARCHAR(30)

השמת ערך למשתנה מקומי

אתחול משתנים מתבצע על ידי פקודת SET. כל משתנה מאותחל על ידי SET נפרד.

SET @local_variable = value

דוגמא.

-- הצהרה של משתנה והשמת ערך
DECLARE @CustomerID CHAR(5) 
SET @CustomerID = 'AROUT'

-- שימוש בערך של המשתנה
SELECT CompanyName, ContactName, Phone 
FROM Customers 
WHERE CustomerID = @CustomerID 

השמה מתוך פעולת Select.

-- מבנה
DECLARE @Local_Variable_1 <Data_Type>, @Local_Variable_2 <Data_Type>,
SET @Local_Variable_1 = (SELECT <Column_1> from <Table_Name> where <Condition_1>)

-- דוגמא
DECLARE @COURSE_NAME VARCHAR (10)
SET @COURSE_NAME = (select Tutorial_name from Guru99 where Tutorial_ID = 3)
PRINT @COURSE_NAME

אפשר לקבל ערך מתוך בסיס הנתונים על ידי SELECT. השאילתא חייבת להחזיר שורה אחת בלבד.

-- מבנה
DECLARE @LOCAL_VARIABLE <Data_Type>
SELECT @LOCAL_VARIABLE = <Value>

--דוגמא
DECLARE @COURSE_ID INT
SELECT @COURSE_ID = 5

-- מבנה לכמה ערכים
DECLARE @Local_Variable _1 <Data_Type>, @Local_Variable _2 <Data_Type>,
SELECT @Local_Variable _1 = <Value_1>,  @Local_Variable _2 = <Value_2>

-- דוגמא. יכול לעשות השמה לכמה ערכים במקביל
DECLARE @COURSE_ID as INT, @COURSE_NAME AS VARCHAR(5)
SELECT @COURSE_ID = 5, @COURSE_NAME = 'UNIX'

-- מבנה השמה מתוך שאילתא. השאילתא חייבת להחזיר שורה אחת ועמודה אחת, כלומר ערך ספציפי.
DECLARE @Local_Variable_1 <Data_Type>, @Local_Variable _2 <Data_Type>,
SELECT @Local_Variable _1 = (SELECT <Column_1> from <Table_name> where <Condition_1>)

-- דוגמא
DECLARE @COURSE_NAME VARCHAR (10)
SELECT @COURSE_NAME = (select Tutorial_name from Guru99 where Tutorial_ID = 1)

הדפסת משתנים

בחוצץ MESSAGE. מקבל רק מחרוזות.

PRINT @local_variable

בחוצץ RESULT.

SELECT @local_variable

תנאים Conditions

פקודת IF.

IF Boolean_expression 
    {sql_statement | statement_block} 
[ELSE 
    {sql_statement | statement_block}]

-- בלוק ליותר מפקודה אחת
BEGIN
    {sql_statement, statement_block}
END

דוגמא

DECLARE @x INT 
SET @x = 1 

IF (1 = @x)
    BEGIN 
        PRINT 'You are number one! '
    END 
ELSE
    BEGIN 
        PRINT 'Loser ;-( '
    END

שימוש ב – Exists בתנאי

EXISTS מאפשר לבחון אם תת השאילתה החזירה שורות כלשהן ומחזירה ערך TRUE או FALSE.

דוגמא:

IF EXISTS (SELECT * 
        FROM Orders 
        WHERE CustomerID = 'VINET') 
    BEGIN
        PRINT 'The Customer has Order'
    END 
ELSE 
    BEGIN 
        DELETE Customers 
        WHERE CustomerID = 'VINET' 
        PRINT 'Customer deleted' 
    END

שימוש בביטויי Case

CASE הוא ביטוי המספק אמצעי להחזרת נתונים שונים המבוסס על בדיקת הערך המוחזר.

דוגמא.

DECLARE 
    @x INT, 
    @Case_result VARCHAR(20) 
SET @x =1 
SET @Case_Result = CASE @x 
                    WHEN 1 THEN 'You are number one!' 
                    WHEN 2 THEN 'Almost …' 
                    ELSE 'Loser :-(' 
                    END 
PRINT @Case_Result

@@ROWCOUNT

משתנה גלובלי אשר מחזיר את מספר הרשומות שהושפעו מפקודה מסויימת.

לולאות – While

לולאת While מאפשרת ביצוע מחזורי.

break – הפסקת הביצוע של הלולאה.

continue – הפסקה של האיטרציה הנוכחית של הלולאה.

-- מבנה
WHILE Boolean_expression 
    {sql_statement | statement_block}

דוגמא

-- מבנה
DECLARE @n INT 
SET @n = 1 

WHILE (SELECT COUNT(*) FROM Employees) >= @n 
    BEGIN 
        IF (SELECT LastName FROM Employees 
            WHERE EmployeeID = @n) = 'King' 
            BEGIN 
                PRINT 'King EmployeeID =' + CAST(@n AS VARCHAR(2)) 
                BREAK 
            END 
        ELSE 
            SET @n = @n + 1 
    END

לולאות GOTO

לולאת GOTO מאפשרת הרצה מחזורית של משפטי ה-SQL כל עוד תנאי שהוגדר מתקיים.

הלולאה תתבצע לפחות פעם אחת והתנאי יבדק לאחר הביצוע הראשון.

LABEL היא לא מילה שמורה, אפשר להשתמש בכל מחרוזת.

-- מבנה
Label:
    Sql_statments | statement block
IF condition GOTO Label

דוגמא:

DECLARE @emp_id NUMERIC(4), 
        @name VARCHAR(30), 
        @b_date DATETIME 
SET @emp_id = 4 

LABEL: 
    SELECT @name =lastname, @b_date = birthdate 
    FROM employees
     WHERE employeeid = @emp_id 
     PRINT @name + CAST(@b_date AS VARCHAR) 
     SET @emp_id = @emp_id +1 

IF @name LIKE '%a%' GOTO LABEL 
PRINT CHAR(10)+'That''s how GOTO LOOP works...'

טיפול בשגיאות

Try… Catch

יש לבצע שימוש בטרנזקציות – במידה ופקודה אחת נכשלת, כל קודמותיה ייכשלו. אחרת, חלק מהפעולות מתבצעות ורק הפעולה עם השגיאה תטופל בהתאם ותכשל.

-- מבנה
BEGIN TRY
    Sql statements
END TRY
BEGIN CATCH
    Sql statements
END CATCH

ניתן לתפוס שגיאות שהתקבלו על ידי שימוש ב:

ERROR_MESSAGE() – ההודעה שהתקבלה

ERROR_NUMBER() – מספר השגיאה

ERROR_LINE() – אינדיקציה למספר השורה בה התקבלה השגיאה

ERROR_PROCEDURE() – הפרוצדורה בה קרתה השגיאה

ERROR_SEVERITY() – חומרת השגיאה

ERROR_STATE() – במידה ויש DISTREBUTED DATE BASES

RAISERROR

דרך נוספת לטיפול בשגיאות, השגיאה עולה בצורה יזומה.

RAISERROR יוצא מהבלוק, שאר הפעולות בבלוק לא יבוצעו ותוצג הודעת שגיאה.

RAISERROR לא סוגר טרנזקציה ולא מבצע ROLLBACK.

-- מבנה
RAISERROR (message_string | message_id | variable ,severity, state [,])

ניתן להוסיף שגיאה ידנית בשימוש ב-system procedure אשר נקראת addmessage.

EXEC sp_addmessage 
    @msgnum = value over 50000, 
    @severity = value between 1 and 25, 
    @msgtext = ‘The message’

@@ERROR – משתנה גלובלי אשר מחזיר את מספר השגיאה האחרונה שהתרחשה. 0 מסמן הצלחה, כל מספר אחר שגיאה.

תרגול T-SQL BASIC

-- ex1
DECLARE @FirstVar CHAR(30), @SecondVar VARCHAR(30)

SET @FirstVar = 'MY FIRST'
SET @SecondVar = 'VARIABLE'

PRINT @FirstVar+' '+@SecondVar

-- ex2
DECLARE @StrPrompt CHAR(30), @TodayDate Date

SET @StrPrompt = 'THE DATE TODAY IS: '
SET @TodayDate = getdate()

PRINT @StrPrompt+cast(@TodayDate as char)

-- ex3
DECLARE @Emp4Name CHAR(30)
SELECT @Emp4Name = (select lastName from Employees where EmployeeID = 4)

PRINT @Emp4Name

-- ex4
DECLARE @Prod5Name CHAR(30), @Prod5Cat CHAR(30)
SELECT @Prod5Name = (select ProductName from Products where ProductID = 5)
SELECT @Prod5Cat = (select c.CategoryName from Products p 
    inner join Categories c on p.CategoryID = c.CategoryID where p.ProductID = 5)

PRINT @Prod5Name+@Prod5Cat

-- ex5
DECLARE @Prod9Price INT

SELECT @Prod9Price = (select unitprice from Products where ProductID = 17)

IF (@Prod9Price > 50)
    BEGIN 
        PRINT 'I LIKE THIS PRODUCT '
    END 
ELSE
    BEGIN 
        PRINT 'I DO NOT LIKE THIS PRODUCT '
    END

select * from Products

-- ex6
DECLARE @ProdName CHAR(50), @ProdPrice INT

SELECT @ProdName = 'Tarte au sucre'
SELECT @ProdPrice = (select unitprice from Products where ProductName = @ProdName)

IF (@ProdPrice < 20)
    BEGIN 
        set @ProdPrice = @ProdPrice * 1.1
        PRINT 'New 10% price '+cast(@ProdPrice as char)
    END 
else IF (@ProdPrice >= 20 and @ProdPrice < 40)
    BEGIN 
        set @ProdPrice = @ProdPrice * 1.2
        PRINT 'New 20% price '+cast(@ProdPrice as char)
    END 
ELSE
    BEGIN 
        set @ProdPrice = @ProdPrice * 1.5
        PRINT 'New 50% price '+cast(@ProdPrice as char)
    END

-- ex7
DECLARE @n INT, @EmpLastName CHAR(20)
SET @n = 1 

WHILE (SELECT COUNT(*) FROM Employees) >= @n 
    BEGIN 
        select @EmpLastName = (SELECT LastName FROM Employees WHERE EmployeeID = @n)

        IF @EmpLastName like '%e%' 
            BEGIN 
                PRINT cast(@n as char)+' - Letter e in last name = ' + @EmpLastName 
                SET @n = @n + 1 
            END 
        ELSE 
            SET @n = @n + 1 
    END

-- ex8
DECLARE @cat_name VARCHAR(30),
        @cat_num INT

SET @cat_num = 4

LABEL: 
    SELECT *
    FROM categories
    WHERE Categoryid = @cat_num

    SELECT @cat_name = categoryname
    FROM categories
    WHERE categoryid = @cat_num
    
    SET @cat_num = @cat_num + 1

IF @cat_name LIKE '%a%'
    GOTO LABEL
ELSE
    SELECT 'NO MORE CATEGORIES WITH THE LETTER A!'



-- מעבר בלולאה על כל הרשומות שיש לי בטבלה
-- פעולה יקרה, אם אין צורך לא משתמשים בה
DECLARE 
    @product_name VARCHAR(250), 
    @list_price  DECIMAL;

DECLARE cursor_product CURSOR
FOR SELECT 
        product_name, 
        list_price
    FROM 
        production.products; --50

OPEN cursor_product;

FETCH NEXT FROM cursor_product INTO 
    @product_name, 
    @list_price;

WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT @product_name + CAST(@list_price AS varchar);
        FETCH NEXT FROM cursor_product INTO 
            @product_name, 
            @list_price;
    END;

CLOSE cursor_product;

DEALLOCATE cursor_product;