The control-of-flow language is quite similar between PL/SQL and Transact-SQL. Regardless of DBMS, the control-of-flow language controls the flow of execution of SQL statements, statement blocks, and stored procedures.
These are the keywords supported by each DBMS.
Statement | PL/SQL | Transact-SQL |
Declare variables | DECLARE | DECLARE |
Statement block | BEGIN...END; | BEGIN...END |
Conditional processing | IF…THEN, ELSIF…THEN, ELSE ENDIF; |
IF…[BEGIN…END] ELSE [BEGIN…END] CASE expression |
Unconditional exit | RETURN | RETURN |
Wait for a specified interval | N/A | WAITFOR |
Loop control | WHILE…END LOOP; LABEL…GOTO LABEL; FOR…END LOOP; LOOP…END LOOP; |
WHILE… LABEL…GOTO LABEL |
Program comments | /* … */, -- | /* … */, -- |
Print output | DBMS_OUTPUT.PUT_LINE | |
Raise program error | RAISE_APPLICATION_ERROR | RAISERROR |
Execute program | EXECUTE | EXECUTE |
Statement terminator | Semicolon (;) | N/A |
Transact-SQL and PL/SQL variables are created using the DECLARE keyword. Transact-SQL variables must be identified with the at sign (@) and, like PL/SQL variables, are initialized to a null value when they are first created.
Oracle | SQL Server |
DECLARE VSSN CHAR(9); VFNAME VARCHAR2(12); VLNAME VARCHAR2(20); VBIRTH_DATE DATE; VLOAN_AMOUNT NUMBER(12,2); |
DECLARE @VSSN CHAR(9), @VFNAME VARCHAR2(12), @VLNAME VARCHAR2(20), @VBIRTH_DATE DATETIME, @VLOAN_AMOUNT NUMERIC(12,2) |
Transact-SQL does not support the %TYPE and %ROWTYPE variable data type definitions. A Transact-SQL variable cannot be initialized in the DECLARE statement. The NOT NULL and CONSTANT keywords cannot be used.
Like Oracle LONG and LONG RAW data types, text and image data types cannot be used for variable declarations. Additionally, the PL/SQL style record and table definitions are not supported.
Oracle offers three ways to assign values to local variables:
SQL Server, in contrast, offers two ways to assign values:
Declaring and assigning local variables in Oracle and SQL Server looks like this.
Oracle | SQL Server |
DECLARE VSSN CHAR(9); VFNAME VARCHAR2(12); VLNAME VARCHAR2(20); BEGIN VSSN := '123448887'; SELECT FNAME, LNAME INTO VFNAME, VLNAME FROM STUDENTS WHERE SSN=VSSN; END; |
DECLARE @VSSN CHAR(9), @VFNAME VARCHAR(12), @VLNAME VARCHAR(20) SELECT @VSSN = '12355887' SELECT @VFNAME=FNAME, @VLNAME=LNAME FROM STUDENTS WHERE SSN = @VSSN |
SQL Server does not offer a constant declaration, nor can you assign variables in the DECLARE statement.
PL/SQL and Transact-SQL support the use of the BEGIN…END terminology to specify statement blocks. Transact-SQL does not require the use of a statement block following the DECLARE statement. The BEGIN…END statement blocks are required for IF statements and WHILE loops if more than one statement is executed.
Oracle | SQL Server |
DECLARE DECLARE VARIABLES ... BEGIN -- THIS IS REQUIRED SYNTAX PROGRAM_STATEMENTS ... IF ...THEN STATEMENT1; STATEMENT2; STATEMENTN; END IF; WHILE ... LOOP STATEMENT1; STATEMENT2; STATEMENTN; END LOOP; END; -- THIS IS REQUIRED SYNTAX |
DECLARE DECLARE VARIABLES ... BEGIN -- THIS IS OPTIONAL SYNTAX PROGRAM_STATEMENTS ... IF ... BEGIN STATEMENT1 STATEMENT2 STATEMENTN END WHILE ... BEGIN STATEMENT1 STATEMENT2 STATEMENTN END END -- THIS IS REQUIRED SYNTAX |
The Transact-SQL conditional statement includes the IF and ELSE terminology. There is no ELSIF as in PL/SQL. However, multiple IF statements can be embedded within each other to achieve the same effect. For extensive conditional tests, it is recommend that you use the CASE statement.
Oracle | SQL Server |
DECLARE VDEGREE_PROGRAM CHAR(1); VDEGREE_PROGRAM_NAME VARCHAR2(20); BEGIN VDEGREE_PROGRAM := 'U'; IF VDEGREE_PROGRAM = 'U' THEN VDEGREE_PROGRAM_NAME := 'Undergraduate'; ELSIF VDEGREE_PROGRAM = 'M' THEN VDEGREE_PROGRAM_NAME := 'Masters'; ELSIF VDEGREE_PROGRAM = 'P' THEN VDEGREE_PROGRAM_NAME := 'PhD'; ELSE VDEGREE_PROGRAM_NAME := 'Unknown'; END IF; END; |
DECLARE @VDEGREE_PROGRAM CHAR(1), @VDEGREE_PROGRAM_NAME VARCHAR(20) SELECT @VDEGREE_PROGRAM = 'U' SELECT @VDEGREE_PROGRAM_NAME = CASE @VDEGREE_PROGRAM WHEN 'U' THEN 'Undergraduate' WHEN 'M' THEN 'Masters' WHEN 'P' THEN 'PhD'. ELSE 'Unknown' END |
Transact-SQL offers the WHILE loop. The PL/SQL unconditional LOOP and FOR LOOP statements are not supported. The GOTO statement can also be used for looping purposes.
WHILE Boolean_expression
{sql_statement | statement_block}
[BREAK] [CONTINUE]
The WHILE loop tests a Boolean expression for the repeated execution of one or more statements. The statement(s) are executed repeatedly as long as the specified expression evaluates to TRUE. If multiple statements are to be executed, they must be placed within a BEGIN…END block.
Oracle | SQL Server |
DECLARE COUNTER NUMBER; BEGIN COUNTER := 0 WHILE (COUNTER <5) LOOP COUNTER := COUNTER + 1; END LOOP; END; |
DECLARE @COUNTER NUMERIC SELECT@COUNTER = 1 WHILE (@COUNTER <5) BEGIN SELECT @COUNTER = @COUNTER +1 END |
Statement execution can be controlled from inside the loop with the BREAK and CONTINUE keywords. The BREAK keyword causes an unconditional exit from the WHILE loop. The CONTINUE keyword causes the WHILE loop to restart, skipping any statements that follow.
The Transact-SQL PRINT statement performs the same operation as the PL/SQL DBMS_OUTPUT.put_line procedure. It is used for printing user-specified messages.
The message limit for the PRINT statement is 255 characters. Variables that are defined using the char or varchar data type can be embedded in the printed statement. If any other data type is used, the CONVERT function must be used. Local variables, global variables, and text can be printed. Both single and double quotes can be used to enclose text.
The Transact-SQL RAISERROR statement returns a user-defined error message and sets a system flag to record that an error has occurred. It is very similar in function to the PL/SQL raise_application_error exception handler.
RAISERROR ({msg_id | msg_str}, severity, state
[, argument1 [, argument2]])
[WITH options]
The RAISERROR statement allows the client to retrieve an entry from the sysmessages table or build a message dynamically with user-specified severity and state information. Once defined, this message is sent back to the client as a server error message.
When converting your PL/SQL programs, it may not be necessary to use the RAISERROR statement. In the following code example, the PL/SQL program uses the raise_application_error exception handler, while the Transact-SQL program uses nothing. The raise_application_error exception handler has been included to prevent the PL/SQL program from possibly returning an ambiguous unhandled exception error message. Instead, it always returns the Oracle error message (SQLERRM) whenever an unanticipated problem occurs.
When a Transact-SQL program fails, it always returns a detailed error message to the client program. Therefore, unless some specialized error handling is required, the RAISERROR statement is not always needed.
Oracle | SQL Server |
CREATE OR REPLACE FUNCTION DEPT_ADMIN.DELETE_DEPT (VDEPT IN VARCHAR2) RETURN NUMBER AS BEGIN DELETE FROM DEPT_ADMIN.DEPT WHERE DEPT = VDEPT; RETURN(SQL%ROWCOUNT); EXCEPTION WHEN OTHER THEN RAISE_APPLICATION_ERROR (-20001,SQLERRM); END DELETE_DEPT; / |
CREATE PROCEDURE DEPT_ADMIN.DELETE_DEPT @VDEPT VARCHAR(4) AS DELETE FROM DEPT_DB.DBO.DEPT WHERE DEPT = @VDEPT RETURN @@ROWCOUNT GO |