What are prepared statements? How are they different from dynamic sql? - sql

I did not see any duplicate questions but wondering if somebody can provide some good examples and specially best practices around these.

Prepared Statements are precompiled statements that you can run multiple times against on the database, and SQLServer won't parse or generate a different execution plan each time you run it. Usually, you run prepared statement in a client context (using JDBC, ADO.NET, ODBC or any other client access technology).
A prepared statement in Java (using JDBC, of course) will be something like:
PreparedStatement ps = conn.prepareStatmente("insert into t(field1) values (?)");
ps.setString(1, "Hello");
ps.executeUpdate();
ps.setStrgin(2, "World");
ps.executeUpdate();
ps.close();
// two rows will be inserted into table t:
// field1 => "Hello"
// field1 => "world"
Dynamic SQL is the ability to run any SQL sentence stored in a dynamic variable (i.e. a string) inside a stored procedure or function in SQLServer. You can find some examples in the link provided.

It'd be easier to explain with some context...
In Java, PreparedStatements are SQL statements in a Java String and supports placeholders you can populate without worrying about escaping single quotes. .NET also has PreparedStatement syntax:
Prepared execution is commonly used by applications to execute the same parameterized SQL statement repeatedly. Prepared execution is faster than direct execution for statements executed more than three or four times because the statement is compiled only once, while statements executed directly are compiled each time they are executed. Prepared execution can also provide a reduction in network traffic because the driver can send an execution plan identifier and the parameter values, rather than an entire SQL statement, to the data source each time the statement is executed.
A step short of using a Stored Procedure...
MySQL's dynamic SQL syntax is also called PreparedStatements...
Dynamic SQL
Dynamic SQL is basically any SQL declared as a string data type - it can be customized before execution. The need for using dynamic SQL comes when you want to do things like dynamic column and/or table references. For example, no SQL supports a string variable to represent the table in the FROM clause (Table Valued Variables are an exception, where supported).
It's important to know the difference between EXEC and EXEC sp_executesql with regard to dynamic SQL on SQL Server. EXEC sp_executesql was added in SQL Server 2005, and you can read more about dynamic SQL on SQL Server in the excellent article: The Curse and Blessings of Dynamic SQL

PreparedStaement is a language construct that provides pre-compiled queries that has already been explained in above answers. One very important benefit of using prepared statements is that they save you from malicious SQL injection attacks. How? you only have placeholder in which you can put in values and no other way to alter the query (pre-compiled), whereas in case of Statements, you can alter the query string. Example:
I have a query to update a table -
UPDATE table_name SET col1 = 40 WHERE id = 'A001';
This can be altered (maliciously) as -
UPDATE table_name SET col1 = 40 WHERE id = 'A001'; DROP TABLE table_name;
And your table is gone!
Dynamic queries are a database construct that helps you to write a query in which you can use bind variables rather using values. These are particularly used in PL/SQL code. Also useful in executing DDL statements. Example code (Oracle):
ip_job_name := 'APP_EXTRACT';
lv_query := 'SELECT 1 FROM user_table WHERE table_name = :tab_name';
BEGIN
EXECUTE IMMEDIATE lv_query INTO lv_tab USING ip_job_name;
EXECUTE IMMEDIATE 'DROP TABLE ' || ip_job_name;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;

Related

Does BigQuery support Dynamic SQL?

We are trying to execute multiple statements in BigQuery using stored procedures. This is a generic stored procedure which can invoked for any table, hence need to execute dynamic statements on any table.
Is there EXEC() like thing in BigQuery to execute dynamically generated queries?
Yes. As of 5/20/2020, BigQuery released dynamic SQL feature for you to achieve the goal.
Dynamic SQL is now available as a beta release in all BigQuery regions. Dynamic SQL lets you generate and execute SQL statements dynamically at runtime. For more information, see EXECUTE IMMEDIATE.
For your scenario, you could have a generic procedure:
CREATE PROCEDURE myTableOperations(tableName STRING)
BEGIN
EXECUTE IMMEDIATE CONCAT("SELECT col1 FROM ", tableName, " WHERE ...");
...
END

Does the prepared SQL statements in a stored procedure make the performance better?

I know there have already been lots of question about stored procedure vs prepared SQL statements, but I want to find out something different - if the prepared statements inside a procedure contribute to the performance of this stored procedure, which means make it better.
I have this question because I was told following points when searching some introduction of these 2 skills.
Stored procedure will store and compile your series of statements in
db, which will reduce the overhead of transferring & compiling.
Prepare statements will be compiled and cached in db for multiple
access which lead to less overhead.
I am puzzled about these 'compile', 'store', and 'overhead' - a little bit abstract.
I use prepared statement to avoid re-parse if it will be called frequently.
However should I use prepared statements (to cache & compile) inside a procedure? Since my procedure would have already been stored and compiled in DB, prepare something inside seems meaningless. (compile what was compiled?)
edit with sample code:
Create or Replace procedure MY_PROCEDURE
Begin
//totally meaningless here?
declare sqlStmt varchar(300);
declare stmt statement;
set sqlStmt='update MY_TABLE set NY_COLUMN=? where NY_COLUMN=?';
prepare stmt from sqlStmt;
execute stmt using 2,1
execute stmt using 4,3
..............
END
Is the the above one better than below, since it only parse the statement once? Or same, because statements in procedure will have been pre-compiled.
Create or Replace procedure MY_PROCEDURE
Begin
update MY_TABLE set NY_COLUMN=2 where NY_COLUMN=1;
update MY_TABLE set NY_COLUMN=4 where NY_COLUMN=3;
..............
END
When you first run a stored procedure the database engine parses the procedure and works out the optimal query plan to use when executing it - it then stores this query plan so that every time you run the procedure it doesn't have to recalculate it.
You can see this youself in Management Studio. If you CREATE or ALTER the stored procedure in question, then open a new query and use:
SET STATISTICS TIME ON
In that same query window run the stored procedure. In the messages tab of the result the first message will be something like:
SQL Server parse and compile time:
CPU time = 1038 ms, elapsed time = 1058 ms.
This is the overhead, execute the query again and you will see that the parse and compile time is now 0.
When you prepare a statement in code you get to take advantage of the same benefit. If you query is 'SELECT * FROM table WHERE #var = '+$var, each time you run that query SQL Server has to parse it and calculate the optimal execution plan. If you use a prepared statement SELECT * FROM table WHERE ?, SQL Server will calculate the optimal execution plan the first time you run the prepared statement, and from then on it can reuse the execution plan as with a stored procedure. The same goes if the statement you are executing is 'EXEC dbo.myProc #var = '+$var, SQL Server would still have to parse this statement each time so a prepared statement should still be used.
You do not need to prepare statements that you write inside stored procedures because they are already compiled as shown above - they are prepared statements in themselves.
On thing you should be aware of when using stored procedure and prepared statements is parameter sniffing.
SQL Server calculates and stores the optimal execution plan for the first variables used, if you happen to execute the stored procedure with some unusual variable on the first run, the execution plan stored may be completely suboptimal for the sorts of variables you typically use.
If you find you can execute a stored procedure from Management Studio and it takes say 2 seconds to execute, but performing the same action in your application takes 20 seconds, it's probably as a result of parameter sniffing.
In DB2 actually the opposite may be true. Statements in an SQL routine are prepared when the routine is compiled. Dynamic SQL statements, as in your example, are prepared during the routine run time.
As a consequence, the preparation of dynamic statements will take into account the most current table and index statistics and other compilation environment settings, such as isolation level, while static statements will use the statistics that were in effect during the routine compilation or the latest bind.
If you want stable execution plans, use static SQL. If your statistics change frequently, you may want to use dynamic SQL (or make sure you rebind your routines' packages accordingly).
The same logic applies to Oracle PL/SQL routines, although the way to recompile static SQL differs -- you'll need to invalidate the corresponding routines.

Sybase - Stored procedure - Store results of a SQL query into an OUTPUT parameter

In a stored procedure, I've to build my own SQL request(because tables names and some properties names are known only at execution time(parameters)).
So Basically I've something like this
EXECUTE IMMEDIATE WITH RESULT SET OFF 'My custom query which select one data'
Usually, I would use the INTO commands, but my parameter is recognized inside the Execute immediate, which seems logic.
(Before you ask: I cannot return this in a result set, the result set is used for another data(and the result of this EXECUTE IMMEDIATE will determine which query I will run(and must be returned)).
How would you approach this problem? I guess it's the same problem on SQL Server-... but I didn't tested on it
You could create a table in compiled Sql and then the dynamic Sql populates it, so that the compiled sql statement after the dynamic part can read the results and update them onto your output params.

Stored procedure SQL SELECT statement issue

I am using SQL Server 2008 Enterprise on Windows Server 2008 Enterprise. In a stored procedure, we can execute a SELECT statement directly. And it could also be executed in this new way, I am wondering which method is better, and why?
New method,
declare #teststatement varchar(500)
set #teststatement = 'SELECT * from sometable'
print #teststatement
exec (#teststatement)
Traditional method,
SELECT * from sometable
regards,
George
FYI: it’s not a new method, it is known as Dynamic SQL.
Dynamic SQL are preferred when we need to set or concatenate certain values into sql statements.
Traditional or normal way sql statements are recommended, because stored procedures are complied. Complied on first run "Stored Procedure are Compiled on First Run"
, execution plan of statements are being created at the time of compilation.
Dynamic sqls are ignored while creating execution plans, because it is taken as string (VARCHAR or NVARCHAR as declared).
Refer following articles for more details about dynamic query and stored procs
Introduction to Dynamic SQL Part 1
Introduction to Dynamic SQL Part 2
Everything you wanted to know about Stored Procedures
The traditional method is safer, because the query is parsed when you save it. The query in the 'exec' method is not parsed and can contain errors.
The "new" way, as mentioned, has nothing to do with SQL 2008. EXEC has been available for quite some time. It's also - in most cases - a Very Bad Idea.
You lose parameterization - meaning you are now vulnerable to SQL Injection. It's ugly and error-prone. It's less efficient. And it creates a new execution scope - meaning it can't share variables, temp tables, etc. - from it's calling stored proc.
sp_executesql is another (and preferred) method of executing dynamic SQL. It's what your client apps use, and it supports parameters - which fixes the most glaring problem of EXEC. However, it too has very limited use cases within a stored proc. About the only redeeming use is when you need a dynamic table or column name. T-SQL does not support a variable for that - so you need to use sp_executesql. The number of times you need or should be doing that are very low.
Bottom line - you'd be best off forgetting you ever heard of it.

How to Parse and Append text to a stored procedure in SQL Server 2005 via a parameter

Does anyone know of a way to append text to a stored procedure from within another stored procedure? I would like to do something like the following in SQL Server 2005:
Declare str as Nvarchar(Max) = ''
set #spStr = dbo.spTest + 'Where testCol1 = ''Test'''
exec(#spStr)
I understand this may open some discussion about SQL injection attacks. I'm simply looking to see if syntax exsists to extend a stored procedure by passing it a where clause dynamically in the above manner.
There is no syntax like this available in Sql Server any version. You've got a couple of options:
You could obviously modify the procedure to include a parameter that the procedure code itself would handle as a filter in the final statement(s) that returned the result set from the procedure call. Though I'd advise against it, you could certainly have a parameter that was just a varchar/nvarchar data type which included the actual 'where' clause you want to add and have the procedure code append it to these final select statement(s) as well
Use the insert/exec syntax to populate a temp table with the results of the stored procedure execution and then simply run a filtered select against that temp table.
There are some options.
You can alter the actual SP using the metadata in INFORMATION_SCHEMA.ROUTINES (not really what I think you are wanting to be doing)
You can parameterize the SP - this should not be vulnerable to injection if the SP uses the variable directly and not to dynamically make SQL.
You might consider using a view or an inline or multi-step table-valued function instead, which can be used like a parameterized view (inline being more efficient) - SELECT * FROM udf_Test WHERE TestCol1 = 'Test'.
You can take the results of the SP and put them in a temporary table or table variable and query against that.