SlideShare ist ein Scribd-Unternehmen logo
1 von 12
Chương 7: Stored procedure
1. Giới thiệu Stored Procedure
       A stored procedure là một tập các lệnh Transact-SQL được đặt tên và được lưu
 trên server. Stored procedures trong SQL Server được thực hiện như các procedure
 trong các ngôn ngữ lập trình khác, chúng cũng có các tham số input và output. Stored
 procedure trả về giá trị trạng thái của lệnh gọi là thành công hay không thành công (và
 lý do thành công).
 SQL Server hỗ trợ 5 loại stored procedures:
       System stored procedures được lưu trong master database, tên của các
 procedure này có tiếp đầu ngữ là SP_. Các procedure này cho phép người quản trị
 hệ thống thực hiện các chức năng của quản trị database. Các system procedure
 này có thể được gọi thực hiện trong tất cả các database.
       Local stored procedures được tạo bởi các user database.
       Temporary stored procedures có thể là local, có tên được bắt đầu bởi ký tự
 #, hoặc global, có tên bắt đầu bởi 2 ký tự ##. Local temporary stored procedures
 có thể dùng trong một session của user đã tạo ra nó; global temporary stored
 procedures có thể dùng cho tất cả các session của users.
       Remote stored procedures là một điểm mới của SQL Server 2000. Chúng ta
 có thể thực hiện một stored procedure trên remote server. Một instance của SQL
 Server 2000 có thể gởi và nhận các lệnh gọi remote stored procedure đến một
 instances của SQL Server 2000 hoặc 7.0
       Extended stored procedures (XP_) được thi hành như một dynamic-link
 libraries (DLLs) được thực hiện bên ngoài môi trường SQL Server.
2. Xử lý của stored procedure




   Xử lý ban đầu (initial processing) của một stored procedure bao gồm việc tạo và thực
 thi lần thứ nhất, đó là lúc mà SQL Server đặt sơ đồ thực thi (execution plans) của stored
 procedure trong procedure cache. Procedure cache một vùng nhớ chứa execution plans
 cho tất cả việc thực thi các lệnh Transact-SQL.
Creation: Các lệnh trong procedure sẽ được phân tích cú pháp theo cú pháp của
T-SQL. Nếu thành công, tên của stored procedure được lưu trong SysObjects
table, còn text, lệnh bên trong lệnh tạo procedure, lưu trong SysComments.
Delayed Name Resolution: cho phép stored procedure tham chiếu đến các đối
tượng chưa tồn tại trong lúc procedure được tạo. Delayed Name resolution được
thực hiện trong lúc procedure được thực hiện
Execution: Lần thứ nhất procedure được thực hiện hoặc khi mà procedure phải
recompile, query processor sẽ đọc procedure trong process được gọi là resolution.
Sau giai đoạn resolution, SQL Server sẽ tạo ra execution plans trong procedure cache
Optimization: Khi một stored procedure thành công trong giai đoạn resolution, SQL
Server query optimizer sẽ phân tích các lệnh Transact-SQL trong stored procedure và
tạo ra một sơ đồ chứa phương thức tối ưu để truy xuất data.
Compilation: Compilation liên quan đến quá trình phân tích và tạo execution plan của
procedure trong procedure cache.




     Xử lý tiếp theo (Subsequent processing) của stored procedures nhanh hơn xử lý
ban đầu. vì SQL Server dùng optimized execution plan trong procedure cache.
     Nếu các điều kiện sau đây thoả, SQL Server sử dụng in-memory plan để thực thi
query subsequently:
- Môi trường hiện hành giống với môi trường trong plan đã được dịch. Các sắp đặt
Server, database, và connection quyết định môi trường này.
- Các đối tượng mà procedure tham chiếu không đòi hỏi name resolution. Các đối tượng
đòi hỏi name resolution khi các đối tượng cùng tên được sở hửu bởi các users khác
nhau. Ví dụ user sales sở hửu table Product, và user development cũng sở hửu table
Product , SQL Server phải quyết định table nào được dùng.
SQL Server execution plans có 2 components chính
Execution Plan: Hầu hết các execution plan nằm trong vùng này. Đây là read-only
data structure mà tất cả các users có thể sử dụng.
Execution Context: Mỗi user có một reusable data structure chứa các dữ liệu riêng
 của họ như các giá trị parameter. Khi một user thực thi một query, và một trong
 các structures không được sử dụng, nó sẽ được khởi tạo lại cho user mới.
3. Ứng dụng Stored Procedure
       Stored procedure có nhiều lợi ích.
 Cho phép lập trình theo hướng modular (modular programming)
 Thực thi nhanh hơn
 Giảm được việc chiếm dụng đường truyền mạng
 Bảo mật.
 Xử lý các chức năng và chia sẽ với các ứng dụng khác
    •          Chia sẽ dữ liệu với các ứng dụng khác, do đó bảo đảm tính nhất quán dữ
       liệu.
    •          Stored procedures có thể thực hiện một công việc, một nhiệm vụ. Các qui
       tắc của công việc này được gói gọn trong các stored procedures có thể được thay
       đổi tại một vị trí. Tất cả các clients có thể sử dụng cùng stored procedures để bảo
       đảm tính nhất quán của dữ liệu.
    •          Nếu một tập hợp các stored procedures hỗ trợ tất cả các chức năng doanh
       nghiệp mà user cần phải thực hiện, user không cần phải truy xuất trực tiếp vào
       table
    •          Cung cấp cơ chế bảo mật. User có thể gán quyền thực thi một procedure
       ngay khi họ không có quyền truy xuất các tables hoặc views được tham chiếu
       trong procedure.
    •          Tăng tính năng thực hiện.
    •          Giảm tải đường truyền mạng. Thay vì gởi hàng trăm lệnh Transact-SQL
       qua mạng, user có thể thực hiện một thao tác phức hợp bằng việc gởi một lệnh
       đơn, giảm số lượng các yêu cầu được truyền giữa client và server.
4. Tạo stored procedure
 Tạo stored procedure bằng lệnh Transact-SQL:
     CREATE PROCEDURE procedure_name [ ; number ]
       [{@parameter data_type}[VARYING][=default][OUTPUT] ][,...n]
     [WITH {RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION }]
     AS sql_statement [ ...n ]
 Trong đó
 procedure_name: là tên của stored procedure. Tên này phải tuân theo qui tắc đặt
 tên và là duy nhất trong một database.
 number: là phần tuỳ chọn được dùng để nhóm các procedure có cùng tên với nhau
 để có thể được xoá một lần với nhau bởi lệnh DROP PROCEDURE. Ví dụ chúng
 ta có thể có các procedure orderproc;1, orderproc;2 .... và khi đó lệnh DROP
 PROCEDURE ORDERPROC sẽ xoá tất cả các procedure trong nhóm đó.
 @parameter: là tham số của procedure. Khi procedure có tham số, giá trị các tham
 số phải được cung cấp khi procedure được thực thi trừ khi tham số có khai báo
giá trị default. Mỗi procedure có tối đa là 2,100 tham số. Chúng ta phải dùng @
để làm ký tự đầu tiên trong tên cho tham số hình thức của procedure.
data_type: là kiểu dữ liệu của tham số bao gồm tất cảc các kiểu dữ liệu. Tuy nhiên
kiểu cursor chỉ được dùng cho OUTPUT parameters. Khi chúng ta chỉ định data
type là cursor, thì tham số VARYING và OUTPUT phải đước dùng.
VARYING: chỉ định rằng result set được hỗ trợ như một output parameter. Tham
số này chỉ áp dụng cho tham số có kiểu cursor.
default: giá trị mặc nhiên của tham số nếu user không truyền giá trị cho tham số
khi procedure được thực thi. Giá trị mặc nhiên này có thể là một giá trị hằng, hoặc
NULL, nó có thế các ký tự đại diện (%, _, [], và [^]) nếu procedure sử dụng tham
số với từ khoá LIKE.
OUTPUT: chỉ định tham có trả giá trị về. Giá trị của tham số output sẽ được trả về
khi procedure này thực thi và từ khoá OUTPUT được dùng để truyền tham số.
RECOMPILE: chỉ định rằng SQL Server sẽ recompiled procedure mỗi khi được
gọi thực hiện.
ENCRYPTION: chỉ định rằng SQL Server mã hoá lệnh tạo procedure khi lưu và
table syscomments
sql_statement: là tập lệnh Transact-SQL để thực hiện nhiệm vụ của procedure.
Thực thi stored procedure:
   EXECUTE procedure_name[;number]
     [ [ @parameter = ] { value | @variable [ OUTPUT ] | [ DEFAULT ] ] [ ,...n ]
   [ WITH RECOMPILE ]
Sau đây là các lưu ý khi tạo proedure:
  •          Procedure có thể tham chiếu đến các tables, view, procedure khác cũng
      như các temporary table
  •          Để tạo một procedure, user phải có quyền CREATE PROCEDURE
      (sysadmin, hoặc database owner)
  •          Kích thước của một procedure tối đa là 128 MB
  •          Các procedure có gọi các procedure khác (nesting stored procedure).
      Chúng ta có thể gọi lồng 32 cấp procedure
  •          Để xem lại nội dung lệnh tạo stored procedure, chúng ta thực thi system
      procedure sp_helptext trong database của procedure đó với tham số là tên của
     procedure.
 •         Không thể kết hợp lệnh create procedure với các lệnh SQL khác để tạo
   thành một bó lệnh (batch)
 •         Chúng ta chỉ có thể tạo procedure trong database hiện hành
 •         Sau khi procedure được tạo thành công, tên của procedure được lưu trong
   table sysobjects
5. Một số ví dụ lệnh tạo stored procedure:
 Ví dụ 1: Tạo procedure với tên UpdatePrice dùng để tăng 10% giá cho tất cả các mặt
 hàng.
       Create procedure UpdatePrice
       As
         update VatTu set GiaMua = GiaMua *1.1
       go
 Sau khi thực hiện thành công việc tạo procedure UpdatePrice, ta có thể thực thi
 procedure này bằng lệnh như sau:
        EXECUTE UpdatePrice
 Hoặc
        EXEC UpdatePrice
 Ví dụ 2: Sau đây là một ví dụ về procedure có tham số. Tạo procedure sẽ xoá các
 khách hàng có địa chỉ bằng với giá trị của tham số nhận.
      Create procedure deletingKhachHang @diachi nvarchar(50)
      As
       delete KhachHang where diachi= @diachi
      Chúng ta có thể thực thi procedure trên với giá trị ‘Binh Dinh’ truyền vào cho
 @diachi bằng nhiều cách như sau:
      EXECUTE deletingKhachHang ‘Binh Dinh’
 hoặc
      EXECUTE deletingKhachHang @diachi=‘ Binh Dinh’
 Ví dụ 3: Sử dụng procedure có tham số có giá trị default. Tạo một procedure có
 lấy ra danh sách các khách hàng có giá trị địa chỉ là tham số truyền vào.
       create procedure DanhsachKhachHang @diachi nvarchar(50) = '%'
       as
         select * from KhachHang where diachi like @diachi
       go
 Chúng thực thi procedure trên với tham số truyền vào như sau:
       exec DanhsachKhachHang ‘Binh Dinh’
       Kết quả cho ra là danh sách các records trong table KhachHang có giá trị là ‘Binh
 Dinh’. Nhưng khi thực thi procedure trên mà không truyền tham số vào, kết quả sẽ trả
 về là toàn bộ các records có trong table KhachHang.
 Ví dụ 4: Tạo procedure có tham số trả về (Output parameter). Xét ví dụ sau:
       create proc SoluongKhachHang
                      @diachi varchar(50) = '%',
                      @total integer OUTPUT
       AS
               SELECT @total = count(*) FROM KhachHang
               WHERE diachi LIKE @diachi
       Go
Procedure trên dùng để đếm có bao nhiêu khách hàng có địa chỉ là tham số truyền
 vào và số lượng đếm được sẽ trả về cho output parameter. Để gọi thực hiện procedure
 trên, ta thực hiện đoạn mã lệnh như sau:
        declare @sluong integer
        exec SoluongKhachHang 'Binh Dinh', @sluong output
        SELECT 'Tong so luong khach hang la:' +str(@sluong,4)

6. Cursor output parameter
       Phần này chúng ta sẽ tìm hiều về cursor output parameter.
 Stored procedures chỉ có thể dùng kiểu cursor cho OUTPUT parameters. Nếu kiểu
 cursor được dùng cho parameter, thì cả hai tham số VARYING và OUTPUT phải được
 chỉ định. Hoặc nếu từ khoá VARYING được dùng cho parameter, thì kiểu dữ liệu của
 parameter đó phải là cursor và phải là OUTPUT parameter.
       Chú ý rằng kiểu cursor không thể gắn với biến của các ứng dụng khác thông qua
 database APIs như OLE DB, ODBC, ADO, và DB-Library. Do vậy, các stored
 procedures với cursor OUTPUT parameters không thể được gọi từ database APIs. Các
 procedures này có thể được gọi từ bó lệnh Transact-SQL, stored procedures, hoặc
 triggers chỉ khi biến cursor OUTPUT được gán cho một biến Transact-SQL local
 cursor.
       Trước khi xét một vài ví dụ về cursor output parameter, chúng ta hãy tìm hiểu về
 kiểu dữ liệu cursor.
 Cú pháp khai báo biến kiểu cursor
    DECLARE cursor_name CURSOR [LOCAL | GLOBAL ]
    [ FORWARD_ONLY | SCROLL ]
    [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
    [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
    FOR select_statement
    [ FOR UPDATE [ OF column_name [ ,...n ] ] ]
 Các tham số trong cú pháp trên có ý nghĩa như sau:
 cursor_name: là tên của biến cursor.
 LOCAL: chỉ định rằng đây là biến cục bộ trong phạm vi của bó lệnh, của
 procedure hoặc trigger mà cursor được khai báo.
 GLOBAL: chỉ định rằng đây là biến toàn cục trong phạm vi connection. Cursor
 này có thể được tham chiếu trong bất kỳ procedure hoặc bó lệnh được thực hiện
 trong một connection. Khi chúng ta không chỉ định biến cursor là local hay
 global, thì mặc nhiên phạm vi này sẽ được qui định bởi thông số default to local
 cursor. Mặc nhiên, thông số này là FALSE, có nghĩa là tất cả các biến cursors
 mặc nhiên là global.
 FORWARD_ONLY: Tham số này chỉ định rằng cursor là forward only, nghĩa là con
 trỏ chỉ di chuyển từ dòng đầu đến dòng cuối mà không thể di chuyển ngược lại.
 Nếu tham số này được chỉ định mà không có tham số STATIC, KEYSET, hay
DYNAMIC, thì cursor sẽ là DYNAMIC cursor. Khi không dùng
FORWARD_ONLY hay SCROLL, thì mặc nhiên là FORWARD_ONLY trừ khi
tham số STATIC, KEYSET, or DYNAMIC được dùng. STATIC, KEYSET, và
DYNAMIC cursors mặc nhiên là SCROLL.
STATIC: dùng tham số này để định nghĩa một cursor, dữ liệu trả về sẽ tạo ra một
bản sao chép tạm để dùng cho cursor. Tất cả các yêu cầu đến cursor sẽ được thực
hiện từ table tạm trong database tempdb; Do vậy mà việc thay đổi xãy ra trên
table cơ sở không ảnh hưởng gì đến cursor này, và cursor này không cho phép cập
nhật.
KEYSET: Chỉ định rằng các thành phần cũng như thứ tự các dòng trong cursor là
cố định khi cursor được open.
DYNAMIC: tham số này dùng để định nghĩa cursor cho phép thay đổi giá trị dữ liệu, các
thành phần cũng như thứ tự các dòng.
FAST_FORWARD: tham số này bao gồm FORWARD_ONLY, READ_ONLY. Tham
số này không thể dùng chung với SCROLL hoặc FOR_UPDATE. READ_ONLY:
không cho phép cập nhật thông qua cursor này.
SCROLL_LOCKS: khi dùng tham số này, thì tại những dòng được cập nhật hoặc xoá
thông qua cursor sẽ được khoá lại. SQL Server sẽ khoá các dòng được đọc vào cursor.
SCROLL_LOCKS không thể dùng chung với FAST_FORWARD.
OPTIMISTIC: SQL Server không khoá các dòng được đọc vào cursor. Tham số
này không được dùng chung với FAST_FORWARD
select_statement: là câu lệnh select để định nghĩa kết quả của cursor. Các từ khoá
COMPUTE, COMPUTE BY, FOR BROWSE, và INTO không được cho phép trong
lệnh select để định nghĩa cursor.
UPDATE [OF column_name [,...n]]: Chỉ định các dòng có thể được cập nhật trong
cursor. Nếu không chỉ định các cột thì mặc nhiên tất cả các cột đều có thể được cập
nhật.
Ví dụ tạo ra một cursor chứa các record trả về bởi lệnh select sau:
      DECLARE KhachHang_cursor CURSOR
        FOR SELECT * FROM KhachHang
     OPEN   KhachHang_cursor
   Sau khi cursor được khai báo, chúng ta phải dùng lệnh OPEN Cursor_Name để mở
cursor. Để lấy một dòng trong cursor, chúng ta phải dùng lệnh FETCH. Cú pháp lệnh
FETCH như sau:
   FETCH
    [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE { n } | RELATIVE { n } ]
           FROM
        ]
   { { cursor_name } | @cursor_variable_name }
   [ INTO @variable_name [ ,...n ] ]
trong đó,
NEXT: di chuyển đến dòng kế tiếp của dòng hiện hành. Đây là tham số default của lệnh
fetch.
PRIOR: di chuyển đến dòng trước của dòng hiện hành
FIRST: di chuyển đến record đầu.
LAST: di chuyển đến record cuối
ABSOLUTE {n}: nếu n là số dương, thì di chuyển đến dòng thứ n tính từ dòng thứ nhất.
Nếu n là số âm, thì di chuyển đến dòng n tính từ dòng cuối.
RELATIVE {n }: nếu n là số dương, thì di chuyển đến n dòng kế tiếp tính từ dòng hiện
hành . Nếu n là số âm, thì di chuyển đến n dòng trước tính từ dòng hiện hành.
cursor_name: tên của cursor
@cursor_variable_name: tên biến cursor
Is the name of a cursor variable referencing the open cursor from which the fetch should
be made.
INTO @variable_name[,...n]: cho phép dữ liệu từ các dòng vào các biến cục bộ. Danh
sách các biến phải có kiểu tương ứng với kiểu của các cột trong record set.
      Sau khi lệnh FETCH thực hiện, giá trị của hàm @@FETCH_STATUS sẽ cho
chúng ta biết lệnh FETCH hợp lệ (có giá trị bằng 0) hay đã đến EOF (khác 0). Chúng ta
có thể sử dụng giá trị trả về của @@FETCH_STATUS để kiểm tra điều kiện vòng lập
khi duyệt tòan bộ các record của cursor.
      Ví dụ sau đây khai báo cursor cho các record trong table KhachHang và
sử dụng FETCH NEXT để duyệt qua các record.

     DECLARE KhachHang_cursor      CURSOR FOR
            SELECT TenKH FROM KhachHang WHERE TenKH LIKE "B%"
            ORDER BY TenKH
     OPEN KhachHang_cursor
     -- di chuyển đến record đầu.
     FETCH NEXT FROM KhachHang_cursor
     --Kiểm tra @@FETCH_STATUS --để xem có        còn dòng nào nữa hay không
             WHILE @@FETCH_STATUS = 0
                BEGIN
                            FETCH NEXT FROM       KhachHang_cursor
               END
            CLOSE KhachHang_cursor
     DEALLOCATE KhachHang_cursor
     GO


     Một ví dụ khác dùng để tạo một cursor và đổ dữ liệu trong các dòng của cursor ra
các biến rồi in ra màn hình.

     -- Khai báo các biến để lưu các giá trị trả     về bởi lệnh FETCH
     DECLARE @TenKH varchar(40)
     DECLARE KhachHang_cursor CURSOR FOR
            SELECT TenKH FROM KhachHang WHERE TenKH LIKE "B%"
ORDER BY TenKH
      OPEN KhachHang_cursor
      -- Đọc dòng thứ nhất và lưu giá trị các cột vào các biến.
      FETCH NEXT FROM KhachHang_cursor INTO @TenKH
      -- Kiểm tra @@FETCH_STATUS để duyệt hết các dòng.
              WHILE @@FETCH_STATUS = 0
                   BEGIN
                      -- Hiển thị các giá trị trong các biến.
                      PRINT "Khach hang: " + @TenKH
                      -- di chuyển đến dòng kế tiếp.
                              FETCH NEXT FROM KhachHang_cursor           INTO   @TenKH
                END
            CLOSE KhachHang_cursor
      DEALLOCATE KhachHang_cursor
      GO
      Và bây giờ     chúng ta xét một ví dụ tạo procedure có cursor output
 parameter.
 Lệnh đầu tiên là tạo một stored procedure mà trong đó có khai báo và mở cursor cho
 table KhachHang:
       CREATE PROCEDURE KhachHang_cursor
              @KhachHang_cursor CURSOR VARYING OUTPUT
       AS
       SET @KhachHang_cursor = CURSOR FORWARD_ONLY STATIC FOR
              SELECT * FROM KhachHang
       OPEN @KhachHang_cursor
       GO
       Kế tiếp, chúng ta khai một biến local cursor, để truyền vào lệnh thực thi procedure
 trên và sau đó duyệt các dòng trong cursor.
       DECLARE @MyCursor CURSOR
       EXEC KhachHang_cursor @KhachHang_cursor = @MyCursor OUTPUT
       WHILE (@@FETCH_STATUS = 0)
       BEGIN
          FETCH NEXT FROM @MyCursor
       END
       CLOSE @MyCursor
       DEALLOCATE @MyCursor
       GO
7. Quản trị Stored Procedure
       Cũng giống như các đối tượng khác trong database, để xoá procedure, chúng ta
 dùng lệnh DROP PROCEDURE và để sửa định nghĩa procedure, chúng ta dùng lệnh
 ALTER PROCEDURE. Cú pháp lệnh ALTER PROCEDURE như sau:
    ALTER PROCEDURE procedure_name [ ; number ]
       [ { @parameter data_type } [ VARYING ] [ = default ] [ OUTPUT ] ] [ ,...n ]
[ WITH { RECOMPILE | ENCRYPTION | RECOMPILE ,
    ENCRYPTION } ]
    AS
       sql_statement [ ...n ]
 Cú pháp này giống lệnh create procedure.
8. Xử lý lỗi trong stored procedure
 i) Dùng lệnh RETURN CODE
       Để tăng tính hiệu quả của stored procedures, chúng ta nên xử lý các thông báo về
 trạng thành công hay không thành công cho user. Khi có lổi xãy ra, chúng ta cũng nên
 cung cấp cho user biết thông tin về lỗi theo cách dễ hiểu nhất. Chúng ta có thể dùng lệnh
 return code để thực hiện công việc này. Giá trị code trả về là 0 để chỉ sự thành công.
 Hiện nay, chúng ta chỉ nên dùng giá trị từ 0 đến -14 để trả giá trị trả về.
 Ví dụ sau đây dùng để tạo procedure DanhSachKhachHang để lấy các record trong
 table HoaDon và KhachHang, lệnh RETURN dùng để trả về tổng số dòng được trả
 về từ kết quả lệnh select.
       CREATE PROCEDURE DanhSachKhachHang
               @MaKH nvarchar (10)
       AS
               SELECT MaHD, KhachHang.MaKH
               FROM HoaDon, KhachHang
               WHERE HoaDon.MaKH = KhachHang.MaKH
                       And KhachHang.MaKH = @MaKH
       RETURN (@@ROWCOUNT)
       Stored procedure cũng cho phép developers tạo các thông báo lổi bằng cách thực
 thi procedure hệ thống sp_addmessage. SQL Server xem các thông báo lổi hệ thống
 giống như các thông báo lổi do người dùng đặt ra. Các thông báo lổi sẽ được lưu trong
 table sysmessages trong database master.
       Ví dụ sau đây sẽ tạo ra một user-defined error message, và khi có lỗi xãy ra, nó sẽ
 được tự động lưu vào Windows aplication log.
       EXEC sp_addmessage @msgnum = 50010, @severity = 10,
         @msgtext = 'Customer cannot be deleted.', @with_log = 'true'
 b) Hàm @@error
     Ngoài ra, SQL Server cũng cung cấp cho chúng ta một hàm hệ thống chứa các
 error number cho hầu hết các lệnh Transact-SQL là @@error. Giá trị trả về của
 hàm này là không nếu lệnh thực hiện thành công. Chúng ta cũng có thể dùng hàm
 này để quyết định xem stored procedure có lỗi hay không. Ví dụ sau đây dùng để
 tạo ra procedure InsertKhachHang. Stored procedure này dùng giá trị trả về của
 hàm @@error để quyết định xem có lỗi xảy ra hay không khi lệnh INSERT được
 thực hiện. Nếu lỗi xảy ra, transaction sẽ roll back.

      CREATE PROCEDURE InsertKhachHang
@MaKH nvarchar (10) = NULL,
     @TenKH nvarchar (30) = NULL,
     @Diachi nvarchar (50) = NULL,
     @DT     nvarchar (15) = NULL,
     @Email nvarchar (30) = NULL
     AS
     BEGIN TRANSACTION
          INSERT KhachHang (MaKH, TenKH, DiaChi, DT, Email)
          VALUES ( @MaKH, @TenKH, @Diachi, @DT, @Email)
          IF @@error <> 0
               BEGIN
                       ROLLBACK TRAN
                       RETURN
              END
          ELSE
             COMMIT TRANSACTION

c) Lệnh RAISERROR
     Lệnh RAISERROR để trả về một thông báo lổi do người dùng định nghĩa, user-
defined error message.
Cú pháp lệnh RAISERROR như sau:
  RAISERROR ( { msg_id | msg_str } { , severity , state } )
Trong đó, các tham số có ý nghĩa như sau:
msg_id: là một mã lỗi được lưu trong table sysmessages.
msg_str: Chuỗi thông báo lỗi. Chuỗi này tối đa dài 400 ký tự, được hỗ trợ theo
định dạng sau:
severity: là số nguyên chỉ mức độ nghiêm trọng của thông báo lỗi. Chúng ta có thể
gán giá trị này nằm trong khoảng từ 0-18, còn phạm vi 19-25 chỉ nên dùng cho
các thành viên sysadmin.
state: là số nguyên tuỳ ý từ 1 đến 127 để mô tả thông tin về trạng thái khẩn cấp của
thông báo lỗi.
Chúng ta xét ví dụ sau đây dùng lệnh RAISERROR để điều khiển lỗi như thế nào.
      CREATE PROCEDURE UpdateCustomerPhone
              @MaKH nvarchar (5) = NULL,
              @DT nvarchar (15) = NULL
      AS
             IF @ MaKH IS NULL
                 BEGIN
                    PRINT 'Kiem tra lai MaKH.'
                   RETURN
             END
      /* Xem khach hang nay co ton tai hay chua? */
IF NOT EXISTS
           (SELECT * FROM KhachHang WHERE MaKH = @MaKH)
    BEGIN
            RAISERROR (50010, 16, 1) --Customer not found.
           RETURN
    END
    BEGIN TRANSACTION
        UPDATE KhachHang SET DT = @DT
        WHERE MaKH = @MaKH
    /* Hien thi thong tin moi*/
    SELECT 'Dien thoai cua ' + @MaKH + ' da thay doi thanh: ' +@DT
COMMIT TRANSACTION
GO

Weitere ähnliche Inhalte

Was ist angesagt?

Bai04 quan ly tien trinh
Bai04   quan ly tien trinhBai04   quan ly tien trinh
Bai04 quan ly tien trinh
Vũ Sang
 
Android Nâng cao-Bài 8-JSON & XML Parsing
Android Nâng cao-Bài 8-JSON & XML ParsingAndroid Nâng cao-Bài 8-JSON & XML Parsing
Android Nâng cao-Bài 8-JSON & XML Parsing
Phuoc Nguyen
 
SQL Cursor - kiểu dữ liệu Cursor (Kiểu dữ liệu con trỏ)
SQL Cursor - kiểu dữ liệu Cursor (Kiểu dữ liệu con trỏ)SQL Cursor - kiểu dữ liệu Cursor (Kiểu dữ liệu con trỏ)
SQL Cursor - kiểu dữ liệu Cursor (Kiểu dữ liệu con trỏ)
Pix Nhox
 
Bai10 he thong bao ve bao mat
Bai10   he thong bao ve bao matBai10   he thong bao ve bao mat
Bai10 he thong bao ve bao mat
Vũ Sang
 
Hỏi tình hình bk tiny bktiny-hdsd
Hỏi tình hình bk tiny   bktiny-hdsdHỏi tình hình bk tiny   bktiny-hdsd
Hỏi tình hình bk tiny bktiny-hdsd
Vu Hung Nguyen
 

Was ist angesagt? (19)

Tip oracle
Tip oracleTip oracle
Tip oracle
 
Cai tien trong lenh t sql cua sql server 2008 (2)
Cai tien trong lenh t sql cua sql server 2008 (2)Cai tien trong lenh t sql cua sql server 2008 (2)
Cai tien trong lenh t sql cua sql server 2008 (2)
 
Linux+02
Linux+02Linux+02
Linux+02
 
Bai04 quan ly tien trinh
Bai04   quan ly tien trinhBai04   quan ly tien trinh
Bai04 quan ly tien trinh
 
Android Nâng cao-Bài 4: Content Provider
Android Nâng cao-Bài 4: Content ProviderAndroid Nâng cao-Bài 4: Content Provider
Android Nâng cao-Bài 4: Content Provider
 
ôn tập dbms
ôn tập dbmsôn tập dbms
ôn tập dbms
 
Trigger, Cursor, Function in SQL Server
Trigger, Cursor, Function in SQL ServerTrigger, Cursor, Function in SQL Server
Trigger, Cursor, Function in SQL Server
 
Cursor & Function trong SQL Server
Cursor & Function trong SQL ServerCursor & Function trong SQL Server
Cursor & Function trong SQL Server
 
Slide Hệ Quản Trị Cơ sở dữ liệu - CHƯƠNG 5
Slide Hệ Quản Trị Cơ sở dữ liệu - CHƯƠNG 5Slide Hệ Quản Trị Cơ sở dữ liệu - CHƯƠNG 5
Slide Hệ Quản Trị Cơ sở dữ liệu - CHƯƠNG 5
 
Android Nâng cao-Bài 8-JSON & XML Parsing
Android Nâng cao-Bài 8-JSON & XML ParsingAndroid Nâng cao-Bài 8-JSON & XML Parsing
Android Nâng cao-Bài 8-JSON & XML Parsing
 
Project name
Project nameProject name
Project name
 
Tai lieu quan tri he thong erp oracle
Tai lieu quan tri he thong erp oracleTai lieu quan tri he thong erp oracle
Tai lieu quan tri he thong erp oracle
 
Web201 slide 2
Web201   slide 2Web201   slide 2
Web201 slide 2
 
SQL Cursor - kiểu dữ liệu Cursor (Kiểu dữ liệu con trỏ)
SQL Cursor - kiểu dữ liệu Cursor (Kiểu dữ liệu con trỏ)SQL Cursor - kiểu dữ liệu Cursor (Kiểu dữ liệu con trỏ)
SQL Cursor - kiểu dữ liệu Cursor (Kiểu dữ liệu con trỏ)
 
Laptrinh jdbc
Laptrinh jdbcLaptrinh jdbc
Laptrinh jdbc
 
Bai10 he thong bao ve bao mat
Bai10   he thong bao ve bao matBai10   he thong bao ve bao mat
Bai10 he thong bao ve bao mat
 
Hỏi tình hình bk tiny bktiny-hdsd
Hỏi tình hình bk tiny   bktiny-hdsdHỏi tình hình bk tiny   bktiny-hdsd
Hỏi tình hình bk tiny bktiny-hdsd
 
Chuong5 dong bo_hoa
Chuong5 dong bo_hoaChuong5 dong bo_hoa
Chuong5 dong bo_hoa
 
Bài 3: Làm việc với kiểu dữ liệu và mã kịch bản - Giáo trình FPT
Bài 3: Làm việc với kiểu dữ liệu và mã kịch bản - Giáo trình FPTBài 3: Làm việc với kiểu dữ liệu và mã kịch bản - Giáo trình FPT
Bài 3: Làm việc với kiểu dữ liệu và mã kịch bản - Giáo trình FPT
 

Ähnlich wie Qtu.vn sql - chuong 7

Hệ điều hành (chương 2)
Hệ điều hành (chương 2)Hệ điều hành (chương 2)
Hệ điều hành (chương 2)
realpotter
 
My sql part 2 - manager mysql server - backup & restore database
My sql   part 2 - manager mysql server - backup & restore databaseMy sql   part 2 - manager mysql server - backup & restore database
My sql part 2 - manager mysql server - backup & restore database
laonap166
 
Lập trình cơ bản: Function, khái niệm hàm, phân loại hàm trong Java (có ví dụ...
Lập trình cơ bản: Function, khái niệm hàm, phân loại hàm trong Java (có ví dụ...Lập trình cơ bản: Function, khái niệm hàm, phân loại hàm trong Java (có ví dụ...
Lập trình cơ bản: Function, khái niệm hàm, phân loại hàm trong Java (có ví dụ...
CodeGym Đà Nẵng
 

Ähnlich wie Qtu.vn sql - chuong 7 (20)

Storedprocedure 140411073406-phpapp02
Storedprocedure 140411073406-phpapp02Storedprocedure 140411073406-phpapp02
Storedprocedure 140411073406-phpapp02
 
HQCSDL_ThuTucaaaaaaaaaaaaaaaaaaaâdâdáwww
HQCSDL_ThuTucaaaaaaaaaaaaaaaaaaaâdâdáwwwHQCSDL_ThuTucaaaaaaaaaaaaaaaaaaaâdâdáwww
HQCSDL_ThuTucaaaaaaaaaaaaaaaaaaaâdâdáwww
 
slide_Chuong 3_ (1).ppt
slide_Chuong 3_ (1).pptslide_Chuong 3_ (1).ppt
slide_Chuong 3_ (1).ppt
 
Process and thread
Process and threadProcess and thread
Process and thread
 
Bài 9: Sao lưu và khôi phục hệ thống Domain - Giáo trình FPT
Bài 9: Sao lưu và khôi phục hệ thống Domain - Giáo trình FPTBài 9: Sao lưu và khôi phục hệ thống Domain - Giáo trình FPT
Bài 9: Sao lưu và khôi phục hệ thống Domain - Giáo trình FPT
 
Yii
YiiYii
Yii
 
Timer kernel linux
Timer kernel linuxTimer kernel linux
Timer kernel linux
 
Cấu trúc hệ điều hành
Cấu trúc hệ điều hànhCấu trúc hệ điều hành
Cấu trúc hệ điều hành
 
Hệ điều hành (chương 2)
Hệ điều hành (chương 2)Hệ điều hành (chương 2)
Hệ điều hành (chương 2)
 
vndscasestudy1-160513170651.pdf
vndscasestudy1-160513170651.pdfvndscasestudy1-160513170651.pdf
vndscasestudy1-160513170651.pdf
 
itlchn 20 - Kien truc he thong chung khoan - Phan 2
itlchn 20 - Kien truc he thong chung khoan - Phan 2itlchn 20 - Kien truc he thong chung khoan - Phan 2
itlchn 20 - Kien truc he thong chung khoan - Phan 2
 
[Cntt] all java
[Cntt] all java[Cntt] all java
[Cntt] all java
 
Rtos 2: time slice vs preeption (cùng mức ưu tiên vs có chiếm quyền
Rtos 2: time slice vs preeption (cùng mức ưu tiên vs có chiếm quyềnRtos 2: time slice vs preeption (cùng mức ưu tiên vs có chiếm quyền
Rtos 2: time slice vs preeption (cùng mức ưu tiên vs có chiếm quyền
 
E learning lab - Tim hieu Cake PHP
E learning lab - Tim hieu Cake PHPE learning lab - Tim hieu Cake PHP
E learning lab - Tim hieu Cake PHP
 
Java Tieng Viet
Java Tieng VietJava Tieng Viet
Java Tieng Viet
 
Bài 3: Triển khai dịch vụ Active Directory - Giáo trình FPT
Bài 3: Triển khai dịch vụ Active Directory - Giáo trình FPTBài 3: Triển khai dịch vụ Active Directory - Giáo trình FPT
Bài 3: Triển khai dịch vụ Active Directory - Giáo trình FPT
 
My sql part 2 - manager mysql server - backup & restore database
My sql   part 2 - manager mysql server - backup & restore databaseMy sql   part 2 - manager mysql server - backup & restore database
My sql part 2 - manager mysql server - backup & restore database
 
Asp
AspAsp
Asp
 
1 giới thiệu-cài đặt oracle
1 giới thiệu-cài đặt oracle1 giới thiệu-cài đặt oracle
1 giới thiệu-cài đặt oracle
 
Lập trình cơ bản: Function, khái niệm hàm, phân loại hàm trong Java (có ví dụ...
Lập trình cơ bản: Function, khái niệm hàm, phân loại hàm trong Java (có ví dụ...Lập trình cơ bản: Function, khái niệm hàm, phân loại hàm trong Java (có ví dụ...
Lập trình cơ bản: Function, khái niệm hàm, phân loại hàm trong Java (có ví dụ...
 

Qtu.vn sql - chuong 7

  • 1. Chương 7: Stored procedure 1. Giới thiệu Stored Procedure A stored procedure là một tập các lệnh Transact-SQL được đặt tên và được lưu trên server. Stored procedures trong SQL Server được thực hiện như các procedure trong các ngôn ngữ lập trình khác, chúng cũng có các tham số input và output. Stored procedure trả về giá trị trạng thái của lệnh gọi là thành công hay không thành công (và lý do thành công). SQL Server hỗ trợ 5 loại stored procedures: System stored procedures được lưu trong master database, tên của các procedure này có tiếp đầu ngữ là SP_. Các procedure này cho phép người quản trị hệ thống thực hiện các chức năng của quản trị database. Các system procedure này có thể được gọi thực hiện trong tất cả các database. Local stored procedures được tạo bởi các user database. Temporary stored procedures có thể là local, có tên được bắt đầu bởi ký tự #, hoặc global, có tên bắt đầu bởi 2 ký tự ##. Local temporary stored procedures có thể dùng trong một session của user đã tạo ra nó; global temporary stored procedures có thể dùng cho tất cả các session của users. Remote stored procedures là một điểm mới của SQL Server 2000. Chúng ta có thể thực hiện một stored procedure trên remote server. Một instance của SQL Server 2000 có thể gởi và nhận các lệnh gọi remote stored procedure đến một instances của SQL Server 2000 hoặc 7.0 Extended stored procedures (XP_) được thi hành như một dynamic-link libraries (DLLs) được thực hiện bên ngoài môi trường SQL Server. 2. Xử lý của stored procedure Xử lý ban đầu (initial processing) của một stored procedure bao gồm việc tạo và thực thi lần thứ nhất, đó là lúc mà SQL Server đặt sơ đồ thực thi (execution plans) của stored procedure trong procedure cache. Procedure cache một vùng nhớ chứa execution plans cho tất cả việc thực thi các lệnh Transact-SQL.
  • 2. Creation: Các lệnh trong procedure sẽ được phân tích cú pháp theo cú pháp của T-SQL. Nếu thành công, tên của stored procedure được lưu trong SysObjects table, còn text, lệnh bên trong lệnh tạo procedure, lưu trong SysComments. Delayed Name Resolution: cho phép stored procedure tham chiếu đến các đối tượng chưa tồn tại trong lúc procedure được tạo. Delayed Name resolution được thực hiện trong lúc procedure được thực hiện Execution: Lần thứ nhất procedure được thực hiện hoặc khi mà procedure phải recompile, query processor sẽ đọc procedure trong process được gọi là resolution. Sau giai đoạn resolution, SQL Server sẽ tạo ra execution plans trong procedure cache Optimization: Khi một stored procedure thành công trong giai đoạn resolution, SQL Server query optimizer sẽ phân tích các lệnh Transact-SQL trong stored procedure và tạo ra một sơ đồ chứa phương thức tối ưu để truy xuất data. Compilation: Compilation liên quan đến quá trình phân tích và tạo execution plan của procedure trong procedure cache. Xử lý tiếp theo (Subsequent processing) của stored procedures nhanh hơn xử lý ban đầu. vì SQL Server dùng optimized execution plan trong procedure cache. Nếu các điều kiện sau đây thoả, SQL Server sử dụng in-memory plan để thực thi query subsequently: - Môi trường hiện hành giống với môi trường trong plan đã được dịch. Các sắp đặt Server, database, và connection quyết định môi trường này. - Các đối tượng mà procedure tham chiếu không đòi hỏi name resolution. Các đối tượng đòi hỏi name resolution khi các đối tượng cùng tên được sở hửu bởi các users khác nhau. Ví dụ user sales sở hửu table Product, và user development cũng sở hửu table Product , SQL Server phải quyết định table nào được dùng. SQL Server execution plans có 2 components chính Execution Plan: Hầu hết các execution plan nằm trong vùng này. Đây là read-only data structure mà tất cả các users có thể sử dụng.
  • 3. Execution Context: Mỗi user có một reusable data structure chứa các dữ liệu riêng của họ như các giá trị parameter. Khi một user thực thi một query, và một trong các structures không được sử dụng, nó sẽ được khởi tạo lại cho user mới. 3. Ứng dụng Stored Procedure Stored procedure có nhiều lợi ích. Cho phép lập trình theo hướng modular (modular programming) Thực thi nhanh hơn Giảm được việc chiếm dụng đường truyền mạng Bảo mật. Xử lý các chức năng và chia sẽ với các ứng dụng khác • Chia sẽ dữ liệu với các ứng dụng khác, do đó bảo đảm tính nhất quán dữ liệu. • Stored procedures có thể thực hiện một công việc, một nhiệm vụ. Các qui tắc của công việc này được gói gọn trong các stored procedures có thể được thay đổi tại một vị trí. Tất cả các clients có thể sử dụng cùng stored procedures để bảo đảm tính nhất quán của dữ liệu. • Nếu một tập hợp các stored procedures hỗ trợ tất cả các chức năng doanh nghiệp mà user cần phải thực hiện, user không cần phải truy xuất trực tiếp vào table • Cung cấp cơ chế bảo mật. User có thể gán quyền thực thi một procedure ngay khi họ không có quyền truy xuất các tables hoặc views được tham chiếu trong procedure. • Tăng tính năng thực hiện. • Giảm tải đường truyền mạng. Thay vì gởi hàng trăm lệnh Transact-SQL qua mạng, user có thể thực hiện một thao tác phức hợp bằng việc gởi một lệnh đơn, giảm số lượng các yêu cầu được truyền giữa client và server. 4. Tạo stored procedure Tạo stored procedure bằng lệnh Transact-SQL: CREATE PROCEDURE procedure_name [ ; number ] [{@parameter data_type}[VARYING][=default][OUTPUT] ][,...n] [WITH {RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION }] AS sql_statement [ ...n ] Trong đó procedure_name: là tên của stored procedure. Tên này phải tuân theo qui tắc đặt tên và là duy nhất trong một database. number: là phần tuỳ chọn được dùng để nhóm các procedure có cùng tên với nhau để có thể được xoá một lần với nhau bởi lệnh DROP PROCEDURE. Ví dụ chúng ta có thể có các procedure orderproc;1, orderproc;2 .... và khi đó lệnh DROP PROCEDURE ORDERPROC sẽ xoá tất cả các procedure trong nhóm đó. @parameter: là tham số của procedure. Khi procedure có tham số, giá trị các tham số phải được cung cấp khi procedure được thực thi trừ khi tham số có khai báo
  • 4. giá trị default. Mỗi procedure có tối đa là 2,100 tham số. Chúng ta phải dùng @ để làm ký tự đầu tiên trong tên cho tham số hình thức của procedure. data_type: là kiểu dữ liệu của tham số bao gồm tất cảc các kiểu dữ liệu. Tuy nhiên kiểu cursor chỉ được dùng cho OUTPUT parameters. Khi chúng ta chỉ định data type là cursor, thì tham số VARYING và OUTPUT phải đước dùng. VARYING: chỉ định rằng result set được hỗ trợ như một output parameter. Tham số này chỉ áp dụng cho tham số có kiểu cursor. default: giá trị mặc nhiên của tham số nếu user không truyền giá trị cho tham số khi procedure được thực thi. Giá trị mặc nhiên này có thể là một giá trị hằng, hoặc NULL, nó có thế các ký tự đại diện (%, _, [], và [^]) nếu procedure sử dụng tham số với từ khoá LIKE. OUTPUT: chỉ định tham có trả giá trị về. Giá trị của tham số output sẽ được trả về khi procedure này thực thi và từ khoá OUTPUT được dùng để truyền tham số. RECOMPILE: chỉ định rằng SQL Server sẽ recompiled procedure mỗi khi được gọi thực hiện. ENCRYPTION: chỉ định rằng SQL Server mã hoá lệnh tạo procedure khi lưu và table syscomments sql_statement: là tập lệnh Transact-SQL để thực hiện nhiệm vụ của procedure. Thực thi stored procedure: EXECUTE procedure_name[;number] [ [ @parameter = ] { value | @variable [ OUTPUT ] | [ DEFAULT ] ] [ ,...n ] [ WITH RECOMPILE ] Sau đây là các lưu ý khi tạo proedure: • Procedure có thể tham chiếu đến các tables, view, procedure khác cũng như các temporary table • Để tạo một procedure, user phải có quyền CREATE PROCEDURE (sysadmin, hoặc database owner) • Kích thước của một procedure tối đa là 128 MB • Các procedure có gọi các procedure khác (nesting stored procedure). Chúng ta có thể gọi lồng 32 cấp procedure • Để xem lại nội dung lệnh tạo stored procedure, chúng ta thực thi system procedure sp_helptext trong database của procedure đó với tham số là tên của procedure. • Không thể kết hợp lệnh create procedure với các lệnh SQL khác để tạo thành một bó lệnh (batch) • Chúng ta chỉ có thể tạo procedure trong database hiện hành • Sau khi procedure được tạo thành công, tên của procedure được lưu trong table sysobjects
  • 5. 5. Một số ví dụ lệnh tạo stored procedure: Ví dụ 1: Tạo procedure với tên UpdatePrice dùng để tăng 10% giá cho tất cả các mặt hàng. Create procedure UpdatePrice As update VatTu set GiaMua = GiaMua *1.1 go Sau khi thực hiện thành công việc tạo procedure UpdatePrice, ta có thể thực thi procedure này bằng lệnh như sau: EXECUTE UpdatePrice Hoặc EXEC UpdatePrice Ví dụ 2: Sau đây là một ví dụ về procedure có tham số. Tạo procedure sẽ xoá các khách hàng có địa chỉ bằng với giá trị của tham số nhận. Create procedure deletingKhachHang @diachi nvarchar(50) As delete KhachHang where diachi= @diachi Chúng ta có thể thực thi procedure trên với giá trị ‘Binh Dinh’ truyền vào cho @diachi bằng nhiều cách như sau: EXECUTE deletingKhachHang ‘Binh Dinh’ hoặc EXECUTE deletingKhachHang @diachi=‘ Binh Dinh’ Ví dụ 3: Sử dụng procedure có tham số có giá trị default. Tạo một procedure có lấy ra danh sách các khách hàng có giá trị địa chỉ là tham số truyền vào. create procedure DanhsachKhachHang @diachi nvarchar(50) = '%' as select * from KhachHang where diachi like @diachi go Chúng thực thi procedure trên với tham số truyền vào như sau: exec DanhsachKhachHang ‘Binh Dinh’ Kết quả cho ra là danh sách các records trong table KhachHang có giá trị là ‘Binh Dinh’. Nhưng khi thực thi procedure trên mà không truyền tham số vào, kết quả sẽ trả về là toàn bộ các records có trong table KhachHang. Ví dụ 4: Tạo procedure có tham số trả về (Output parameter). Xét ví dụ sau: create proc SoluongKhachHang @diachi varchar(50) = '%', @total integer OUTPUT AS SELECT @total = count(*) FROM KhachHang WHERE diachi LIKE @diachi Go
  • 6. Procedure trên dùng để đếm có bao nhiêu khách hàng có địa chỉ là tham số truyền vào và số lượng đếm được sẽ trả về cho output parameter. Để gọi thực hiện procedure trên, ta thực hiện đoạn mã lệnh như sau: declare @sluong integer exec SoluongKhachHang 'Binh Dinh', @sluong output SELECT 'Tong so luong khach hang la:' +str(@sluong,4) 6. Cursor output parameter Phần này chúng ta sẽ tìm hiều về cursor output parameter. Stored procedures chỉ có thể dùng kiểu cursor cho OUTPUT parameters. Nếu kiểu cursor được dùng cho parameter, thì cả hai tham số VARYING và OUTPUT phải được chỉ định. Hoặc nếu từ khoá VARYING được dùng cho parameter, thì kiểu dữ liệu của parameter đó phải là cursor và phải là OUTPUT parameter. Chú ý rằng kiểu cursor không thể gắn với biến của các ứng dụng khác thông qua database APIs như OLE DB, ODBC, ADO, và DB-Library. Do vậy, các stored procedures với cursor OUTPUT parameters không thể được gọi từ database APIs. Các procedures này có thể được gọi từ bó lệnh Transact-SQL, stored procedures, hoặc triggers chỉ khi biến cursor OUTPUT được gán cho một biến Transact-SQL local cursor. Trước khi xét một vài ví dụ về cursor output parameter, chúng ta hãy tìm hiểu về kiểu dữ liệu cursor. Cú pháp khai báo biến kiểu cursor DECLARE cursor_name CURSOR [LOCAL | GLOBAL ] [ FORWARD_ONLY | SCROLL ] [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ] FOR select_statement [ FOR UPDATE [ OF column_name [ ,...n ] ] ] Các tham số trong cú pháp trên có ý nghĩa như sau: cursor_name: là tên của biến cursor. LOCAL: chỉ định rằng đây là biến cục bộ trong phạm vi của bó lệnh, của procedure hoặc trigger mà cursor được khai báo. GLOBAL: chỉ định rằng đây là biến toàn cục trong phạm vi connection. Cursor này có thể được tham chiếu trong bất kỳ procedure hoặc bó lệnh được thực hiện trong một connection. Khi chúng ta không chỉ định biến cursor là local hay global, thì mặc nhiên phạm vi này sẽ được qui định bởi thông số default to local cursor. Mặc nhiên, thông số này là FALSE, có nghĩa là tất cả các biến cursors mặc nhiên là global. FORWARD_ONLY: Tham số này chỉ định rằng cursor là forward only, nghĩa là con trỏ chỉ di chuyển từ dòng đầu đến dòng cuối mà không thể di chuyển ngược lại. Nếu tham số này được chỉ định mà không có tham số STATIC, KEYSET, hay
  • 7. DYNAMIC, thì cursor sẽ là DYNAMIC cursor. Khi không dùng FORWARD_ONLY hay SCROLL, thì mặc nhiên là FORWARD_ONLY trừ khi tham số STATIC, KEYSET, or DYNAMIC được dùng. STATIC, KEYSET, và DYNAMIC cursors mặc nhiên là SCROLL. STATIC: dùng tham số này để định nghĩa một cursor, dữ liệu trả về sẽ tạo ra một bản sao chép tạm để dùng cho cursor. Tất cả các yêu cầu đến cursor sẽ được thực hiện từ table tạm trong database tempdb; Do vậy mà việc thay đổi xãy ra trên table cơ sở không ảnh hưởng gì đến cursor này, và cursor này không cho phép cập nhật. KEYSET: Chỉ định rằng các thành phần cũng như thứ tự các dòng trong cursor là cố định khi cursor được open. DYNAMIC: tham số này dùng để định nghĩa cursor cho phép thay đổi giá trị dữ liệu, các thành phần cũng như thứ tự các dòng. FAST_FORWARD: tham số này bao gồm FORWARD_ONLY, READ_ONLY. Tham số này không thể dùng chung với SCROLL hoặc FOR_UPDATE. READ_ONLY: không cho phép cập nhật thông qua cursor này. SCROLL_LOCKS: khi dùng tham số này, thì tại những dòng được cập nhật hoặc xoá thông qua cursor sẽ được khoá lại. SQL Server sẽ khoá các dòng được đọc vào cursor. SCROLL_LOCKS không thể dùng chung với FAST_FORWARD. OPTIMISTIC: SQL Server không khoá các dòng được đọc vào cursor. Tham số này không được dùng chung với FAST_FORWARD select_statement: là câu lệnh select để định nghĩa kết quả của cursor. Các từ khoá COMPUTE, COMPUTE BY, FOR BROWSE, và INTO không được cho phép trong lệnh select để định nghĩa cursor. UPDATE [OF column_name [,...n]]: Chỉ định các dòng có thể được cập nhật trong cursor. Nếu không chỉ định các cột thì mặc nhiên tất cả các cột đều có thể được cập nhật. Ví dụ tạo ra một cursor chứa các record trả về bởi lệnh select sau: DECLARE KhachHang_cursor CURSOR FOR SELECT * FROM KhachHang OPEN KhachHang_cursor Sau khi cursor được khai báo, chúng ta phải dùng lệnh OPEN Cursor_Name để mở cursor. Để lấy một dòng trong cursor, chúng ta phải dùng lệnh FETCH. Cú pháp lệnh FETCH như sau: FETCH [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE { n } | RELATIVE { n } ] FROM ] { { cursor_name } | @cursor_variable_name } [ INTO @variable_name [ ,...n ] ] trong đó,
  • 8. NEXT: di chuyển đến dòng kế tiếp của dòng hiện hành. Đây là tham số default của lệnh fetch. PRIOR: di chuyển đến dòng trước của dòng hiện hành FIRST: di chuyển đến record đầu. LAST: di chuyển đến record cuối ABSOLUTE {n}: nếu n là số dương, thì di chuyển đến dòng thứ n tính từ dòng thứ nhất. Nếu n là số âm, thì di chuyển đến dòng n tính từ dòng cuối. RELATIVE {n }: nếu n là số dương, thì di chuyển đến n dòng kế tiếp tính từ dòng hiện hành . Nếu n là số âm, thì di chuyển đến n dòng trước tính từ dòng hiện hành. cursor_name: tên của cursor @cursor_variable_name: tên biến cursor Is the name of a cursor variable referencing the open cursor from which the fetch should be made. INTO @variable_name[,...n]: cho phép dữ liệu từ các dòng vào các biến cục bộ. Danh sách các biến phải có kiểu tương ứng với kiểu của các cột trong record set. Sau khi lệnh FETCH thực hiện, giá trị của hàm @@FETCH_STATUS sẽ cho chúng ta biết lệnh FETCH hợp lệ (có giá trị bằng 0) hay đã đến EOF (khác 0). Chúng ta có thể sử dụng giá trị trả về của @@FETCH_STATUS để kiểm tra điều kiện vòng lập khi duyệt tòan bộ các record của cursor. Ví dụ sau đây khai báo cursor cho các record trong table KhachHang và sử dụng FETCH NEXT để duyệt qua các record. DECLARE KhachHang_cursor CURSOR FOR SELECT TenKH FROM KhachHang WHERE TenKH LIKE "B%" ORDER BY TenKH OPEN KhachHang_cursor -- di chuyển đến record đầu. FETCH NEXT FROM KhachHang_cursor --Kiểm tra @@FETCH_STATUS --để xem có còn dòng nào nữa hay không WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM KhachHang_cursor END CLOSE KhachHang_cursor DEALLOCATE KhachHang_cursor GO Một ví dụ khác dùng để tạo một cursor và đổ dữ liệu trong các dòng của cursor ra các biến rồi in ra màn hình. -- Khai báo các biến để lưu các giá trị trả về bởi lệnh FETCH DECLARE @TenKH varchar(40) DECLARE KhachHang_cursor CURSOR FOR SELECT TenKH FROM KhachHang WHERE TenKH LIKE "B%"
  • 9. ORDER BY TenKH OPEN KhachHang_cursor -- Đọc dòng thứ nhất và lưu giá trị các cột vào các biến. FETCH NEXT FROM KhachHang_cursor INTO @TenKH -- Kiểm tra @@FETCH_STATUS để duyệt hết các dòng. WHILE @@FETCH_STATUS = 0 BEGIN -- Hiển thị các giá trị trong các biến. PRINT "Khach hang: " + @TenKH -- di chuyển đến dòng kế tiếp. FETCH NEXT FROM KhachHang_cursor INTO @TenKH END CLOSE KhachHang_cursor DEALLOCATE KhachHang_cursor GO Và bây giờ chúng ta xét một ví dụ tạo procedure có cursor output parameter. Lệnh đầu tiên là tạo một stored procedure mà trong đó có khai báo và mở cursor cho table KhachHang: CREATE PROCEDURE KhachHang_cursor @KhachHang_cursor CURSOR VARYING OUTPUT AS SET @KhachHang_cursor = CURSOR FORWARD_ONLY STATIC FOR SELECT * FROM KhachHang OPEN @KhachHang_cursor GO Kế tiếp, chúng ta khai một biến local cursor, để truyền vào lệnh thực thi procedure trên và sau đó duyệt các dòng trong cursor. DECLARE @MyCursor CURSOR EXEC KhachHang_cursor @KhachHang_cursor = @MyCursor OUTPUT WHILE (@@FETCH_STATUS = 0) BEGIN FETCH NEXT FROM @MyCursor END CLOSE @MyCursor DEALLOCATE @MyCursor GO 7. Quản trị Stored Procedure Cũng giống như các đối tượng khác trong database, để xoá procedure, chúng ta dùng lệnh DROP PROCEDURE và để sửa định nghĩa procedure, chúng ta dùng lệnh ALTER PROCEDURE. Cú pháp lệnh ALTER PROCEDURE như sau: ALTER PROCEDURE procedure_name [ ; number ] [ { @parameter data_type } [ VARYING ] [ = default ] [ OUTPUT ] ] [ ,...n ]
  • 10. [ WITH { RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ] AS sql_statement [ ...n ] Cú pháp này giống lệnh create procedure. 8. Xử lý lỗi trong stored procedure i) Dùng lệnh RETURN CODE Để tăng tính hiệu quả của stored procedures, chúng ta nên xử lý các thông báo về trạng thành công hay không thành công cho user. Khi có lổi xãy ra, chúng ta cũng nên cung cấp cho user biết thông tin về lỗi theo cách dễ hiểu nhất. Chúng ta có thể dùng lệnh return code để thực hiện công việc này. Giá trị code trả về là 0 để chỉ sự thành công. Hiện nay, chúng ta chỉ nên dùng giá trị từ 0 đến -14 để trả giá trị trả về. Ví dụ sau đây dùng để tạo procedure DanhSachKhachHang để lấy các record trong table HoaDon và KhachHang, lệnh RETURN dùng để trả về tổng số dòng được trả về từ kết quả lệnh select. CREATE PROCEDURE DanhSachKhachHang @MaKH nvarchar (10) AS SELECT MaHD, KhachHang.MaKH FROM HoaDon, KhachHang WHERE HoaDon.MaKH = KhachHang.MaKH And KhachHang.MaKH = @MaKH RETURN (@@ROWCOUNT) Stored procedure cũng cho phép developers tạo các thông báo lổi bằng cách thực thi procedure hệ thống sp_addmessage. SQL Server xem các thông báo lổi hệ thống giống như các thông báo lổi do người dùng đặt ra. Các thông báo lổi sẽ được lưu trong table sysmessages trong database master. Ví dụ sau đây sẽ tạo ra một user-defined error message, và khi có lỗi xãy ra, nó sẽ được tự động lưu vào Windows aplication log. EXEC sp_addmessage @msgnum = 50010, @severity = 10, @msgtext = 'Customer cannot be deleted.', @with_log = 'true' b) Hàm @@error Ngoài ra, SQL Server cũng cung cấp cho chúng ta một hàm hệ thống chứa các error number cho hầu hết các lệnh Transact-SQL là @@error. Giá trị trả về của hàm này là không nếu lệnh thực hiện thành công. Chúng ta cũng có thể dùng hàm này để quyết định xem stored procedure có lỗi hay không. Ví dụ sau đây dùng để tạo ra procedure InsertKhachHang. Stored procedure này dùng giá trị trả về của hàm @@error để quyết định xem có lỗi xảy ra hay không khi lệnh INSERT được thực hiện. Nếu lỗi xảy ra, transaction sẽ roll back. CREATE PROCEDURE InsertKhachHang
  • 11. @MaKH nvarchar (10) = NULL, @TenKH nvarchar (30) = NULL, @Diachi nvarchar (50) = NULL, @DT nvarchar (15) = NULL, @Email nvarchar (30) = NULL AS BEGIN TRANSACTION INSERT KhachHang (MaKH, TenKH, DiaChi, DT, Email) VALUES ( @MaKH, @TenKH, @Diachi, @DT, @Email) IF @@error <> 0 BEGIN ROLLBACK TRAN RETURN END ELSE COMMIT TRANSACTION c) Lệnh RAISERROR Lệnh RAISERROR để trả về một thông báo lổi do người dùng định nghĩa, user- defined error message. Cú pháp lệnh RAISERROR như sau: RAISERROR ( { msg_id | msg_str } { , severity , state } ) Trong đó, các tham số có ý nghĩa như sau: msg_id: là một mã lỗi được lưu trong table sysmessages. msg_str: Chuỗi thông báo lỗi. Chuỗi này tối đa dài 400 ký tự, được hỗ trợ theo định dạng sau: severity: là số nguyên chỉ mức độ nghiêm trọng của thông báo lỗi. Chúng ta có thể gán giá trị này nằm trong khoảng từ 0-18, còn phạm vi 19-25 chỉ nên dùng cho các thành viên sysadmin. state: là số nguyên tuỳ ý từ 1 đến 127 để mô tả thông tin về trạng thái khẩn cấp của thông báo lỗi. Chúng ta xét ví dụ sau đây dùng lệnh RAISERROR để điều khiển lỗi như thế nào. CREATE PROCEDURE UpdateCustomerPhone @MaKH nvarchar (5) = NULL, @DT nvarchar (15) = NULL AS IF @ MaKH IS NULL BEGIN PRINT 'Kiem tra lai MaKH.' RETURN END /* Xem khach hang nay co ton tai hay chua? */
  • 12. IF NOT EXISTS (SELECT * FROM KhachHang WHERE MaKH = @MaKH) BEGIN RAISERROR (50010, 16, 1) --Customer not found. RETURN END BEGIN TRANSACTION UPDATE KhachHang SET DT = @DT WHERE MaKH = @MaKH /* Hien thi thong tin moi*/ SELECT 'Dien thoai cua ' + @MaKH + ' da thay doi thanh: ' +@DT COMMIT TRANSACTION GO