The PL/SQL Channel Writing Dynamic SQL in Oracle PL/SQL Best Practices for Dynamic SQL Steven Feuerstein steven@stevenfeuerstein.com www.stevenfeuerstein.com www.plsqlchallenge.com
Quick Reminders Download code and PowerPoint documents from www.toadworld.com/sf (aka, "PL/SQL Obsession"). Make sure you are comfortable with the material covered in the previous lessons in this series. Introduction and Overview; Executing Dynamic DDL, DML, Queries and PL/SQL Blocks; Dynamic SQL Method 4 Copyright 2010 Feuerstein and Associates Page 2
Best Practices for Dynamic SQL Stored programs with dynamic SQL should be defined as AUTHID CURRENT_USER. Consider making your dynamic DDL programs autonomous transactions. Always EXECUTE IMMEDIATE a variable, not a literal string. Avoid concatenation; bind whenever possible. Take steps to avoid SQL injection vulnerabilities. Copyright 2010 Feuerstein and Associates Page 3
Use AUTHID CURRENT_USER (invoker rights) This best practice applies to stored program units that execute dynamic SQL, and can be called from other schemas. In this case, consider defining those programs with AUTHID CURRENT_USER. Otherwise, the dynamic SQL operation could have an unintended effect. Objects in the SQL statements will be resolved using the privileges of the owner, not the invoker. dropwhatever_authid.sql Copyright 2010 Feuerstein and Associates Page 4
Use Autonomous Transaction with Dynamic DDL When a DDL statement is executed, Oracle performs an implicit commit. Executing DDL in PL/SQL will, therefore, also commit any outstanding changes in your session. To avoid this, use the autonomous transaction Pragma to limit the scope of the commit. dropwhatever.sp Copyright 2010 Feuerstein and Associates Page 5
EXECUTE IMMEDIATE a variable, not literal It isn't hard to learn the syntax for using EXECUTE IMMEDIATE. The hard part is constructing the often very complex SQL statement. Always construct that statement and assign it to a variable. Then EXECUTE IMMEDIATE the variable. Then if something goes wrong you can log or view the statement and more easily identify the mistake you made. dropwhatever.sp Copyright 2010 Feuerstein and Associates Page 6
Bind Whenever Possible When you SQL statement needs to use values of variables in your block, you have two choices: Concatenate those values directly into the dynamic SQL string. Bind the value into the string through a placeholder. Generally, you should avoid concatenation, and bind whenever possible. Benefits include: The resulting code is much easier to use. You can avoid unnecessary parsing, since the SQL statement is not physically changing. Minimize the chance of injection (covered later). useconcat*.* usebinding.sp toomuchbinding.sp ultrabind.* Copyright 2010 Feuerstein and Associates Page 7
SQL (code) Injection "Injection" means that unintended and often malicious code is inserted into a dynamic SQL statement. Biggest risk occurs with dynamic PL/SQL, but it is also possible to subvert SQL statements. SQL injection is a very complex topic and cannot be adequately addressed in this lesson. I will go over the basics, but recommend you study up with the experts... Alexander Kornbrust at www.red-database-security.com Pete Finnegan at www.petefinnegan.com Copyright 2010 Feuerstein and Associates Page 8
Protection from SQL Injection Restrict privileges tightly on external user schemas. No create, drop, etc. privileges Use bind variables whenever possible. You can't inject through a value. Check dynamic text for dangerous text. Use DBMS_ASSERT to validate object names, like tables and views. Preface all built-in packages with "SYS." code_injection.sql sql_guard.* dbms_assert_demo.sql Copyright 2010 Feuerstein and Associates Page 9
NDS or DBMS_SQL: Which should you use? Reasons to go with native dynamic SQL: Ease of use Works with all SQL datatypes (including userdefined object and collection types) Fetch into records and collections of records Usually faster runtime performance Why You'd Use DBMS_SQL: Method 4 Dynamic SQL DESCRIBE columns of cursor SQL statements larger than 32K (prior to 11g) Better reuse of parsed SQL statements -- persistent cursor handles! Bottom line: Native dynamic SQL should be your first choice. And in Oracle11g, you can move back and forth between the two approaches, to optimize the use of both. Copyright 2010 Feuerstein and Associates Page 10
Dynamic SQL Conclusions The increased complexity of dynamic SQL means that you need to take more care to write code that is easy to understand and maintain. The techniques recommended in this lesson will help you achieve this goal. Copyright 2010 Feuerstein and Associates Page 11
Next Steps Download the demo.zip if you have not already (www.toadworld.com/sf). Run the sample code yourself to better understand the features and techniques. Apply all that you have learned in this series! Copyright 2010 Feuerstein and Associates Page 12