Đó là câu hỏi.
Một bài đăng gần đây trên diễn đàn OTN đã hỏi về việc sử dụng dấu chấm phẩy và dấu gạch chéo làm dấu chấm dứt câu lệnh. Tôi đã kết thúc một bài báo mà tôi đã viết cho nhóm phát triển của chúng tôi hơn 4 năm trước về chủ đề này. Bài viết này nhận được đánh giá tốt và có sẵn trên các diễn đàn OTN nếu muốn. Tôi nghĩ tôi cũng sẽ đăng nó trên blog của mình. Đây là bài viết:
Slash hoặc No Slash
bởi Brian Peasland
Tại công ty của chúng tôi, các tập lệnh SQL được triển khai được thực thi trong tiện ích dòng lệnh SQL * Plus của Oracle, trong khi nhiều nhà phát triển sử dụng công cụ GUI như PL / SQL Developer hoặc SQL Developer. Dấu gạch chéo chuyển tiếp có nghĩa là một cái gì đó đối với SQL * Plus không cần thiết trong PL / SQL Developer hoặc SQL Developer. Do đó, có thể gây nhầm lẫn khi biết liệu bạn có cần thêm dấu gạch chéo vào trong các tập lệnh SQL của mình hay không. Hy vọng rằng phần này sẽ làm sáng tỏ những gì mà dấu gạch chéo phía trước làm, khi nào thì sử dụng và khi nào thì không nên sử dụng. Dấu chấm phẩy chấm dứt Đối với hầu hết các câu lệnh SQL, dấu chấm phẩy là dấu chấm dứt câu lệnh. Ví dụ:hãy xem xét câu lệnh SQL đơn giản này chạy trong SQL * Plus:
SQL> chọn sysdate từ kép;
SYSDATE
———
18-THÁNG 6 -12
Khi SQL * Plus nhìn thấy dấu chấm phẩy, nó biết rằng đã đến cuối câu lệnh SQL và bây giờ nó có thể thực thi lệnh.
SQL * Plus Buffer
Bạn có thể không biết rằng SQL * Plus có bộ đệm cho các lệnh của nó. Nếu tôi nhấn phím ‘l’ cho ‘danh sách’, thì tôi có thể thấy lệnh hiện có trong bộ đệm phiên của tôi.
SQL> l
1 * chọn sysdate từ kép
Không có gì đáng ngạc nhiên, có lệnh mà tôi vừa thực hiện. Sau đó, tôi đã thực thi một câu lệnh SQL khác và đây là cách bộ đệm của tôi bây giờ trông như thế nào:
SQL> l
1 chọn ngày mã hóa, người dùng
2 * từ kép
Như bạn có thể thấy, bây giờ tôi có hai dòng trong bộ đệm SQL * Plus của phiên của tôi.
Slash =Thực thi bộ đệm
Quy tắc đầu tiên cần hiểu về dấu gạch chéo là đối với SQL * Plus, dấu gạch chéo lên có nghĩa là thực thi nội dung của bộ đệm. Để minh họa khái niệm này, tôi sẽ thực thi một câu lệnh SQL, đợi một vài giây và sau đó chỉ thực thi lại câu lệnh SQL đó nhưng chỉ thực thi bộ đệm.
SQL> select to_char (sysdate, 'MM / DD / YYYY HH24:MI:SS ’) từ kép;
TO_CHAR (SYSDATE, 'MM
——————-
18/06/2012 15:20:40
SQL> /
TO_CHAR (SYSDATE, 'MM
——————-
18/06/2012 15:21:17
SQL> /
TO_CHAR (SYSDATE, 'MM
——————-
18/06/2012 15:21:50
Bạn có thể thấy rằng tất cả những gì tôi đã làm trong lần thứ hai và thứ ba là chỉ cần nhập ‘/’ và nhấn enter và SQL * Plus thực thi nội dung của bộ đệm lệnh mỗi lần.
Khối PL / SQL
Dấu chấm dứt câu lệnh dấu chấm phẩy hoạt động tốt cho đến khi Oracle giới thiệu PL / SQL trong phiên bản Oracle 7. Vấn đề là các khối PL / SQL có thể có nhiều dấu chấm phẩy để kết thúc các câu lệnh riêng lẻ tạo nên khối đó. Hãy xem xét khối PL / SQL rất đơn giản này không có tác dụng gì:
SQL> bắt đầu
2 null;
3 null;
4 cuối;
5
Dòng 2 và 3 chứa các câu lệnh hoàn toàn hợp lệ, mỗi câu được kết thúc bằng dấu chấm phẩy. Và ở dòng 4, chúng ta có từ khóa END biểu thị sự kết thúc của khối PL / SQL. Nếu chúng ta không được phép sử dụng các cặp BEGIN / END lồng nhau, thì mỗi khi SQL * Plus nhìn thấy “END;” nó sẽ biết phần cuối của khối PL / SQL đã đạt đến, nhưng chúng tôi được phép sử dụng các cặp BEGIN / END lồng nhau để những điều sau đây là hoàn toàn hợp pháp và hợp lệ:
SQL> bắt đầu
2 bắt đầu
3 null;
4 cuối;
5 rỗng;
6 kết thúc;
7
Bạn có thể nói ở trên rằng chỉ cần tìm kiếm “END;” là không đủ vì SQL * Plus đã cố gắng chạy khối sau dòng 4. Vậy làm cách nào Oracle quyết định thông báo rằng khối PL / SQL đã sẵn sàng thực thi? Câu trả lời là bằng cách sử dụng dấu gạch chéo phía trước như bạn có thể đã biết. Quy tắc thứ hai cần hiểu là tất cả các dấu gạch chéo tiến được thực hiện khi bạn sử dụng nó để kết thúc khối PL / SQL là yêu cầu SQL * Plus chạy những gì có trong bộ đệm! Điều này đã không thay đổi kể từ trước khi PL / SQL được tạo cho Oracle 7. Hãy xem xét mẫu sau:
SQL> bắt đầu
2 null;
3 kết thúc;
4 /
Thủ tục PL / SQL đã hoàn tất thành công.
SQL> l
1 begin
2 null;
3 * kết thúc;
Trên dòng 4, tôi đã nhập dấu gạch chéo lên để thực thi khối PL / SQL. Bạn có thể thấy rằng khối của tôi đã hoàn thành thành công. Nếu chúng ta quay lại và xem nội dung của bộ đệm lệnh của tôi, bạn có thể thấy nó chứa mọi thứ trừ dấu gạch chéo. Dấu gạch chéo về phía trước không phải là một phần của bộ đệm lệnh. Vì vậy, bây giờ, tôi sẽ chạy một khối PL / SQL khác:
SQL> bắt đầu
2 dbms_output.put_line (‘Hôm nay là‘ || to_char (sysdate, ’MM / DD / YYYY HH24:MI:SS’));
3 kết thúc;
4 /
Hôm nay là 18/06/2012 15:39:32
Thủ tục PL / SQL đã hoàn tất thành công.
Dấu gạch chéo chuyển tiếp cho SQL * Plus để chạy những gì có trong bộ đệm của nó và kết quả được hiển thị. Bây giờ chúng ta hãy nhập lại chỉ dấu gạch chéo và chúng ta sẽ thấy khối PL / SQL của chúng ta được thực thi trở lại.
SQL> /
Hôm nay là 18/06/2012 15:40:42
Thủ tục PL / SQL đã hoàn tất thành công.
Tôi không phải nhập lại khối PL / SQL của mình vì nó hiện đang ở trong bộ đệm lệnh.
PL / SQL và SQL Developer và PL / SQL Blocks
Vấn đề lớn nhất đối với hầu hết các nhà phát triển là PL / SQL Developer và SQL Developer không yêu cầu bạn sử dụng dấu gạch chéo. Tại sao? Vì bạn có thể nhấn Execute (F8) hoặc Run Script (F5) để chạy khối PL / SQL của mình. PL / SQL Developer biết rằng thời điểm bạn nhấn F8, bạn đang có ý định gửi khối PL / SQL sẽ được thực thi. Trong trường hợp này, F8 trong PL / SQL Developer đang thực hiện công việc tương tự như dấu gạch chéo trong SQL * Plus. Tương tự, đối với F5 trong SQL Developer.
Vấn đề ở công ty của tôi là nhóm của chúng tôi triển khai mã cho sản xuất không triển khai mã với PL / SQL Developer hoặc SQL Developer. Họ sử dụng SQL * Plus vì việc viết kịch bản nhiều lần thực thi dễ dàng hơn với công cụ dòng lệnh. Nhiều nhà phát triển mắc sai lầm khi không đưa dấu gạch chéo lên phía trước cho các khối PL / SQL trong các tập lệnh vì họ không cần nó, nhưng nếu bạn muốn triển khai phần mã đó trong một tập lệnh SQL, thì cần có dấu gạch chéo ở cuối mỗi PL. / Khối SQL.
Khi nào không nên sử dụng Slash
Vì vậy, chúng ta đã biết khi nào và tại sao chúng ta sử dụng dấu gạch chéo trước, nhưng khi nào thì không tốt khi sử dụng? Quy tắc thứ ba cần biết là việc sử dụng dấu gạch chéo sau một câu lệnh SQL đơn (không nằm trong khối PL / SQL) là không tốt, đặc biệt khi dấu gạch chéo đó ngay sau câu lệnh DML (CHÈN, CẬP NHẬT hoặc XÓA). Nếu tập lệnh của tôi chứa những điều sau:
chọn sysdate từ kép;
/
Sau đó, tôi sẽ nhận được "đầu ra gấp đôi" mà không phải là những gì tôi thường dự định làm trong một kịch bản. Tôi thực sự chỉ muốn trả về một dòng chứ không phải hai dòng như đoạn mã trên sẽ làm:
SQL> chọn sysdate từ kép;
SYSDATE
———
18-JUN-12
SQL> /
SYSDATE
———
18-THÁNG 6 -12
Nó thậm chí còn tệ hơn khi tôi sử dụng dấu gạch chéo sau một câu lệnh DML vì câu lệnh đó sẽ được thực thi hai lần. Hãy xem xét tập lệnh sau:
chèn vào giá trị test_tab (10);
/
Bây giờ chúng ta biết rằng khi tôi thực thi hai dòng trên trong một tập lệnh, SQL * Plus sẽ thực thi nó một lần do dấu chấm phẩy câu lệnh kết thúc và sau đó thực thi lần thứ hai vì dấu gạch chéo chuyển tiếp yêu cầu SQL * Plus chạy những gì có trong bộ đệm lệnh. Khi tôi thực thi tập lệnh hai dòng ở trên, tôi nhận được kết quả sau:
SQL> chèn vào giá trị test_tab (10);
Đã tạo 1 hàng.
SQL>
/
chèn vào các giá trị test_tab (10) *
LỖI tại dòng 1:ORA-00001:ràng buộc duy nhất (PEASLAND.SYS_C00767176) bị vi phạm
Giáo sư! Lần chèn đầu tiên đã hoạt động (đã tạo 1 hàng.) Nhưng khi nhập dấu gạch chéo lên, SQL * Plus đã cố gắng chèn cùng một dữ liệu và tôi đã mắc phải một lỗi vi phạm ràng buộc duy nhất.
Kết luận
Hy vọng rằng, trang này cho thấy lý do tại sao cần sử dụng dấu gạch chéo phía trước, những gì nên làm và khi nào không nên sử dụng nó. Tóm lại:
- Bao gồm dấu gạch chéo phía trước ở cuối mỗi khối PL / SQL
- Không bao gồm dấu gạch chéo sau bất kỳ câu lệnh SQL nào không có trong khối PL / SQL.
- Dấu gạch chéo sau một câu lệnh SQL sẽ khiến lệnh SQL đó thực thi hai lần.