Can we write DML statements (Insert/Update) inside snowflake udf rather than procedure.
UDFs can contain SQL or JavaScript; however, DDL and DML operations are not supported in UDFs.
Details: https://docs.snowflake.com/en/sql-reference/ddl-udf.html#udf-management
UDF is meant to be used in a SELECT statement by passing a column into it. If you need to run DML statement inside a UDF, I can see there is some sort of design issue here.
UDFs can contain SQL or JavaScript; however, DDL and DML operations
are not supported in UDFs.
Related
I often use a stored procedure for data access purpose but don't know which one is best - a view or a stored procedure or a function?
Please tell me which one of the above is best for data access purpose and why it is best, list down the reason with the example please.
I searched Google to learn which one is best but got no expected answer
View
A view is a “virtual” table consisting of a SELECT statement, by means of “virtual”
I mean no physical data has been stored by the view -- only the definition of the view is stored inside the database; unless you materialize the view by putting an index on it.
By definition you can not pass parameters to the view
NO DML operations (e.g. INSERT, UPDATE, and DELETE) are allowed inside the view; ONLY SELECT statements.
Most of the time, view encapsulates complex joins so it can be reusable in the queries or stored procedures. It can also provide level of isolation and security by hiding sensitive columns from the underlying tables.
Stored procedure
A stored procedure is a group of Transact-SQL statements compiled into a single execution plan or in other words saved collection of Transact-SQL statements.
A stored procedure:
accepts parameters
can NOT be used as building block in a larger query
can contain several statements, loops, IF ELSE, etc.
can perform modifications to one or several tables
can NOT be used as the target of an INSERT, UPDATE or DELETE statement
A view:
does NOT accept parameters
can be used as building block in a larger query
can contain only one single SELECT query
can NOT perform modifications to any table
but can (sometimes) be used as the target of an INSERT, UPDATE or DELETE statement.
Functions
Functions are subroutines made up of one or more Transact-SQL statements that can be used to encapsulate code for reuse
There are three types (scalar, table valued and inline mutlistatement) UDF and each of them server different purpose you can read more about functions or UDF in BOL
UDF has a big limitation; by definition it cannot change the state of the database. What I mean by this you cannot perform data manipulation operation inside UDF (INSERT, UPDATE , DELETE) etc.
SP are good for doing DDL statements that you can't do with functions. SP and user defined functions accept parameters and can returns values but they can't do the same statements.
User defined functions can only do DML statements.
View doesn't accept parameters, and only accept DML statements.
I hope below information will help you to understand the use of the SQL procedure, view, and function.
Stored Procedure - Stored Procedure can be used for any database operation like insert, update, delete and fetch which you mentioned that you are already using.
View - View only can be used to fetch the data but it has limitations as you can't pass the parameters to the view. e.g. filter the data based on the passed parameter
Function - Function usually used for a specific operation like you have many in-built SQL server functions also for the date, for math, for string manipulation etc.
I'll make it very short and straight.
When you are accessing data from different tables and don't want to pass parameter use View.
When you want to perform DML statement go for Function.
When you want to perform DDL statement go for Stored Procedure.
Rest is upon your knowledge and idea hit in your mind at particular point of time.
And for performance reasons many would argue
- avoid functions (especially scalar) if possible
It's easier to tweak stored procedures (query plans) and views
IMO, View (and Indexed View) are just Fancier SELECT
Stored Procedure are versatile as you can transform/manipulate within
I have been doing a lot of reading up on execution plans and the problems of dynamic parameters in stored procedures. I know the suggested solutions for this.
My question, though, is everything I have read indicated that SQL Server caches the execution plan for stored procedures. No mention is made of Table-value functions. I assume it does so for Views (out of interest).
Does it recompile each time a Table-value function is called?
When is it best to use a Table-value function as opposed to a stored procedure?
An inline table valued function (TVF) is like a macro: it's expanded into the outer query. It has no plan as such: the calling SQL has a plan.
A multi-statement TVF has a plan (will find a reference).
TVFs are useful where you want to vary the SELECT list for a parameterised input. Inline TVFs are expanded and the outer select/where will be considered by the optimiser. For multi-statement TVFs optimisation is not really possible because it must run to completion, then filter.
Personally, I'd use a stored proc over a multi-statement TVF. They are more flexible (eg hints, can change state, SET NOCOUNT ON, SET XACTABORT etc).
I have no objection to inline TVFs but don't tend to use them for client facing code because of the inability to use SET and change state.
I haven't verified this, but I take for granted that the execution plan for functions are also cached. I can't see a reason why that would not be possible.
The execution plan for views are however not cached. The query in the view will be part of the query that uses the view, so the execution plan can be cached for the query that uses the view, but not for the view itself.
The use of functions versus stored procedured depends on what result you need from it. A table-valued function can return a single result, while a stored procedure can return one result, many results, or no result at all.
I don't know why, but CLR User Defined Functions are not allowed to update tables.
Is it possible to work around this restriction by calling a stored procedure from the CLR UDF that updates tables for it ?
It is not CLR UDF, it is any RDBMS UDF function, by definition, cannot change the state of a database, i.e. engage:
DELETE, INSERT, UPDATE (i.e. DML) statements,
calls to stored procedure,
permanently change the value of server environment variable,
etc.
as well as use calls to nondeterministic (with the same input returning different results) functions (like GETDATE(), NEWID(), etc.)
Update:
Oops, SQL Server 2008 relaxed the restrictions on use of non-deterministic functions.
If UDF uses non-deterministic, then it is treated as non-deterministic.
One can check it by:
SELECT OBJECTPROPERTY(OBJECT_ID('dbo.FunctionName'),'IsDeterministic')
I have a relatively complex query, with several self joins, which works on a rather large table.
For that query to perform faster, I thus need to only work with a subset of the data.
Said subset of data can range between 12 000 and 120 000 rows depending on the parameters passed.
More details can be found here: SQL Server CTE referred in self joins slow
As you can see, I was using a CTE to return the data subset before, which caused some performance problems as SQL Server was re-running the Select statement in the CTE for every join instead of simply being run once and reusing its data set.
The alternative, using temporary tables worked much faster (while testing the query in a separate window outside the UDF body).
However, when I tried to implement this in a multi-statement UDF, I was harshly reminded by SQL Server that multi-statement UDFs do not support temporary tables for some reason...
UDFs do allow table variables however, so I tried that, but the performance is absolutely horrible as it takes 1m40 for my query to complete whereas the CTE version only took 40 seconds.
I believe the table variables is slow for reasons listed in this thread: Table variable poor performance on insert in SQL Server Stored Procedure
Temporary table version takes around 1 seconds, but I can't make it into a function due to the SQL Server restrictions, and I have to return a table back to the caller.
Considering that CTE and table variables are both too slow, and that temporary tables are rejected in UDFs, What are my options in order for my UDF to perform quickly?
Thanks a lot in advance.
In many such cases all we need to do is to declare primary keys for those table variables, and it is fast again.
Set up and use a Process-Keyed Table, See the article: from How to Share Data Between Stored Procedures by Erland Sommarskog
One kludgey work-around I've used involves code like so (psuedo code follows):
CREATE TEMP TABLE #foo
EXECUTE MyStoredProcedure
SELECT *
from #foo
GO
-- Stored procedure definition
CREATE PROCEDURE MyStoredProcedure
AS
INSERT #foo values (whatever)
RETURN
GO
In short, the stored procedure references and uses a temp table created by the calling procedure (or routine). This will work, but it can be confusing for others to follow what's going on if you don't document it clearly, and you will get recompiles, statistics recalcs, and other oddness that may consume unwanted clock cycles.
I'm trying to use SQL Server Profiler (2005) to track down some application performance problems. One of the calls being made is to a table-valued user-defined function. This function wraps a select that joins several tables together.
In SQL Server Profiler, the call to the UDF is logged. However, the select that underlies the UDF isn't being logged at all. Because of this, I'm not getting useful data on which tables & indexes are being hit. I'd like to feed this info into the Database Tuning Advisor for some indexing advice.
Is there any way (short of unwrapping the queries themselves) to log the tables called by UDFs in Profiler?
You can't: a multi-statement TVF is a black box and you can only get CPU, Read, Writes etc.
by "black box" I mean it's a fully encapsulated and opaque series of statements inside another query, and there is no "flow" like you'd get line by line through a stored proc.
An in-line TVF is expanded like a view or macro into the main query and can be seen.
Edit: related: Table Valued Function where did my query plan go?