[SQL][MCSA]70-461 筆記 (四)

[SQL][MCSA]70-461 筆記 (四)

 

Modify Data (24%)

  • Create and alter stored procedures (simple statements).

    • May include but not limited to: write a stored procedure to meet a given set of requirements; branching logic; create stored procedures and other programmatic objects; techniques for developing stored procedures; different types of storeproc result; create stored procedure for data access layer; program stored procedures, triggers, functions with T-SQL
  • Modify data by using INSERT, UPDATE, and DELETE statements.

    • May include but not limited to: given a set of code with defaults, constraints, and triggers, determine the output of a set of DDL; know which SQL statements are best to solve common requirements; use output statement
  • Combine datasets.

    • May include but not limited to: difference between UNION and UNION all; case versus isnull versus coalesce; modify data by using MERGE statements
  • Work with functions.

    • May include but not limited to: understand deterministic, non-deterministic functions; scalar and table values; apply built-in scalar functions; create and alter user-defined functions (UDFs)

 


 

Store Procedure

建立的語法

--Transact-SQL Stored Procedure Syntax
CREATE { PROC | PROCEDURE } [schema_name.] procedure_name [ ; number ] 
    [ { @parameter [ type_schema_name. ] data_type } 
        [ VARYING ] [ = default ] [ OUT | OUTPUT ] [READONLY]
    ] [ ,...n ] 
[ WITH <procedure_option> [ ,...n ] ]
[ FOR REPLICATION ] 
AS { [ BEGIN ] sql_statement [;] [ ...n ] [ END ] }
[;]
 
<procedure_option> ::= 
    [ ENCRYPTION ]
    [ RECOMPILE ]
    [ EXECUTE AS Clause ]

 

刪除的語法

DROP { PROC | PROCEDURE } { [ schema_name. ] procedure } [ ,...n ]

 

修改的語法

--Transact-SQL Stored Procedure Syntax
ALTER { PROC | PROCEDURE } [schema_name.] procedure_name [ ; number ] 
    [ { @parameter [ type_schema_name. ] data_type } 
        [ VARYING ] [ = default ] [ OUT | OUTPUT ] [READONLY]
    ] [ ,...n ] 
[ WITH <procedure_option> [ ,...n ] ]
[ FOR REPLICATION ] 
AS { [ BEGIN ] sql_statement [;] [ ...n ] [ END ] }
[;]
 
<procedure_option> ::= 
    [ ENCRYPTION ]
    [ RECOMPILE ]
    [ EXECUTE AS Clause ]

 

優點 ( MSDN : http://msdn.microsoft.com/zh-tw/library/ms190782(v=sql.110).aspx )

  • 安全性
    • 多個使用者和用戶端程式都可以透過程序,在基礎資料庫物件上執行作業,即使使用者和程式不具備這些基礎物件的直接權限亦可。 程序也會控制要執行哪些程序和活動,並保護基礎資料庫物件。 這可避免在個別物件層級授與權限的需求,而簡化安全層。
    • EXECUTE AS 子句可指定在 CREATE PROCEDURE 陳述式中模擬其他使用者,或讓使用者或應用程式執行特定資料庫活動,而不需要具備基礎物件和指令的直接權限。
  • 提升效能
    • 預設第一次編譯程序時,將建立執行計畫並執行,以利後續的執行中重複使用。 由於查詢處理器不需要建立新計畫,通常可以花較少的時間來處理程序。

 

RECOMPLIER : There are three ways to do this:

    • WITH RECOMPILE option in the procedure definition or when the procedure is called,
    • the RECOMPILE query hint on individual statements
    • Using the sp_recompile system stored procedure.

 

案例說明

-- grants EXECUTE permission on the stored procedure to an application role named Recruiting11.
GRANT EXECUTE ON OBJECT::HumanResources.uspUpdateEmployeeHireInfo
    TO Recruiting11;
-- stored procedure with an input and an output parameter.
CREATE PROCEDURE Sales.uspGetEmployeeSalesYTD
@SalesPerson nvarchar(50),
@SalesYTD money OUTPUT
AS  
    SET NOCOUNT ON;
    SELECT @SalesYTD = SalesYTD
    FROM Sales.SalesPerson AS sp
    JOIN HumanResources.vEmployee AS e ON e.BusinessEntityID = sp.BusinessEntityID
    WHERE LastName = @SalesPerson;
RETURN
-- Declare the variable to receive the output value of the procedure.
DECLARE @SalesYTDBySalesPerson money;
-- Execute the procedure specifying a last name for the input parameter
-- and saving the output value in the variable @SalesYTDBySalesPerson
EXECUTE Sales.uspGetEmployeeSalesYTD
    N'Blythe', @SalesYTD = @SalesYTDBySalesPerson OUTPUT;

 

 

EXECUTE AS

  • 可以定義使用者自訂模組 ( Function 、Stored Procedure 、Queue和 Trigger )的執行內容。
  • CALLER : 預設值,指定模組內的陳述式,是在該模組的呼叫者內容當中執行。
  • SELF : 相當於 EXECUTE AS user_name,其中指定的使用者,就是建立或變更模組的人。
  • OWNER : 指定模組內的陳述式,是在該模組目前擁有者的內容中執行。 如果該模組沒有指定的擁有者,則會採用該模組的結構描述擁有者。

 


 

DML

INSERT

[ WITH <common_table_expression> [ ,...n ] ]
INSERT 
{
        [ TOP ( expression ) [ PERCENT ] ] 
        [ INTO ] 
        { <object> | rowset_function_limited 
          [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
        }
    {
        [ ( column_list ) ] 
        [ <OUTPUT Clause> ]
        { VALUES ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n     ] 
        | derived_table 
        | execute_statement
        | <dml_table_source>
        | DEFAULT VALUES 
        }
    }
}
[;]
  • 在 SQL 2008 之後可允許一次 Insert 多組
CREATE TABLE dbo.Table1 
    (ColA int NOT NULL, ColB decimal(10,3) NOT NULL);
GO
INSERT INTO dbo.Table1 VALUES(1, 10.0), (1, 20.0), (1, 30.0);

 

 

UPDATE

[ WITH <common_table_expression> [...n] ]
UPDATE 
    [ TOP ( expression ) [ PERCENT ] ] 
    { { table_alias | <object> | rowset_function_limited 
         [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
      }
      | @table_variable    
    }
    SET
        { column_name = { expression | DEFAULT | NULL }
          | { udt_column_name.{ { property_name = expression
                                | field_name = expression }
                                | method_name ( argument [ ,...n ] )
                              }
          }
          | column_name { .WRITE ( expression , @Offset , @Length ) }
          | @variable = expression
          | @variable = column = expression
          | column_name { += | -= | *= | /= | %= | &= | ^= | |= } expression
          | @variable { += | -= | *= | /= | %= | &= | ^= | |= } expression
          | @variable = column { += | -= | *= | /= | %= | &= | ^= | |= } expression
        } [ ,...n ] 
 
    [ <OUTPUT Clause> ]
    [ FROM{ <table_source> } [ ,...n ] ] 
    [ WHERE { <search_condition> 
            | { [ CURRENT OF 
                  { { [ GLOBAL ] cursor_name } 
                      | cursor_variable_name 
                  } 
                ]
              }
            } 
    ] 
    [ OPTION ( <query_hint> [ ,...n ] ) ]
[ ; ]
  • 在 SQL Server 下如果使用 Update 配合 CTE 的時候,則 CTE 的處理要寫在 Update 指令之前 ( 和 Oracle 的不相同 )
  • 在指定異動欄位的處理值時,可以用較精簡的 [複合指派運算子] ( += | -= | *= | /= | %= | &= | ^= | |= ),樣式類似 C++ 的寫法。
  • 可以配合 WHERE CURRENT OF 和 Cursor 變數配合,利用 Cursor 來修改資料。
  • 指定 FROM 子句來提供更新作業的準則時,請特別小心。 如果 UPDATE 陳述式包括 FROM 子句,且這個 FROM 子句的指定方式並非每個更新的資料行項目都只能使用一個值,也就是說,如果 UPDATE 陳述式不具決定性,UPDATE 陳述式的結果便未定義。配合上述的 Insert Sample,雖然會有三筆符合條件,但只會取第一筆來做更新,則下面的 Table2 的欄位 ColB 會是 10
CREATE TABLE dbo.Table2 
    (ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL);
GO
INSERT INTO dbo.Table2 VALUES(1, 0.0);
GO
UPDATE dbo.Table2 
SET dbo.Table2.ColB += dbo.Table1.ColB
FROM dbo.Table2 
    INNER JOIN dbo.Table1 
    ON (dbo.Table2.ColA = dbo.Table1.ColA);
GO

 

 

 

 

DELETE

[ WITH <common_table_expression> [ ,...n ] ]
DELETE 
    [ TOP ( expression ) [ PERCENT ] ] 
    [ FROM ] 
    { { table_alias
      | <object> 
      | rowset_function_limited 
      [ WITH ( table_hint_limited [ ...n ] ) ] } 
      | @table_variable
    }
    [ <OUTPUT Clause> ]
    [ FROM table_source [ ,...n ] ] 
    [ WHERE { <search_condition> 
            | { [ CURRENT OF 
                   { { [ GLOBAL ] cursor_name } 
                       | cursor_variable_name 
                   } 
                ]
              }
            } 
    ] 
    [ OPTION ( <Query Hint> [ ,...n ] ) ] 
[; ]
  • 當刪除包含 FILESTREAM 資料行的資料列時,也會刪除其基礎檔案系統的檔案。

 

 

OUTPUT

  • DELETED : 資料行前置詞,用來指定更新或刪除作業所刪除的值,反映 UPDATE、DELETE 或 MERGE 陳述式完成之前的值。
  • INSERTED : 資料行前置詞,用來指定插入或更新作業所加入的值,反映 UPDATE、INSERT 或 MERGE 陳述式完成之後、觸發程序執行之前的值,不能用來搭配使用 DELETE 陳述式中的 OUTPUT 子句。
  • 可同時混搭 OUTPUT 和 OUTPUT … INTO 來使用 

 

 

MERGE

[ WITH <common_table_expression> [,...n] ]
MERGE 
    [ TOP ( expression ) [ PERCENT ] ] 
    [ INTO ] <target_table> [ WITH ( <merge_hint> ) ] [ [ AS ] table_alias ]
    USING <table_source> 
    ON <merge_search_condition>
    [ WHEN MATCHED [ AND <clause_search_condition> ]
        THEN <merge_matched> ] [ ...n ]
    [ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]
        THEN <merge_not_matched> ]
    [ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]
        THEN <merge_matched> ] [ ...n ]
    [ <output_clause> ]
    [ OPTION ( <query_hint> [ ,...n ] ) ]    
;

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

幾種常使用的條件判斷

 

CASE : 最傳統的使用方式,要用 END 來做結束,最多只允許 10 層。當如果判斷的條件是從 1 開始的數字時,則可以考慮用 CHOOSE 函數來做取代

 

COALESCE : SQL 2012 新提供的,很容易和 ISNULL 混淆。最主要的差異是 COALESCE 是可以傳入多個參數,但一定要有一個是不能 NULL 的值,否則會有異常。但 ISNULL 只能傳入兩個參數,若第一個參數不是 NULL,則回傳該參數;若是 NULL 則回傳第二個參數值。

 

NULLIF:當兩個值都相等的時候回傳 NULL,最常配合 Aggregate 類的函數使用,因此像是 Count , Avg 這類的函數都會忽略不去考慮 NULL 值。

 

 

 

案例說明

 

 


UDF ( MSDN Link : http://msdn.microsoft.com/zh-tw/library/ms177499.aspx )

  • 使用者定義純量函數會傳回在 RETURNS 子句中所定義類型的單一資料值,傳回類型可以是任何資料類型,但 text、ntext、image、cursor 和 timestamp 除外。
  • 使用者定義資料表值函式會傳回 table 資料類型。內嵌資料表值函式並沒有函數主體;資料表為單一 SELECT 陳述式的結果集。
-- User-defined scalar function 
CREATE FUNCTION dbo.ufnGetInventoryStock(@ProductID int)
RETURNS int 
AS 
BEGIN
    DECLARE @ret int;
    SELECT @ret = ISNULL(SUM(p.Quantity),0) FROM Production.ProductInventory p  WHERE p.ProductID = @ProductID 
    RETURN @ret;
END;
 
-- Inline table-valued function,
CREATE FUNCTION Sales.ufn_SalesByStore (@storeid int)
RETURNS TABLE

		AS
		
 
RETURN
(
     P.ProductID, P.Name, (SD.LineTotal)  
SELECTSUMAS'Total'
     Production.Product  P 
FROMAS
     Sales.SalesOrderDetail  SD  SD.ProductID = P.ProductID
JOINASON
     Sales.SalesOrderHeader  SH  SH.SalesOrderID = SD.SalesOrderID
JOINASON
     Sales.Customer  C  SH.CustomerID = C.CustomerID
JOINASON
     C.StoreID = @storeid
WHERE
      P.ProductID, P.Name
GROUPBY
);
 

		-- Multistatement table-valued function,
		
  dbo.ufn_FindReports (@InEmpID )
CREATEFUNCTIONINTEGER
 @retFindReports  
RETURNSTABLE
(
    EmployeeID     ,
intprimarykeyNOTNULL
    FirstName nvarchar(255)  ,
NOTNULL
    LastName nvarchar(255)  
NOTNULL
)

		AS
		

		BEGIN
		
   INSERT @retFindReports   EmployeeID, FirstName, LastName   EMP 
SELECTFROM
   
RETURN
;
END