I have a large number of stored procedures (200+) that all collect clinical data and insert the result into a common table. Each stored procedure accepts the same single parameter, ClientID, and then compiles a list of diagnostic results and inserts them into a master table.
I have each clinical test separated into individual stored procedures however as I described in a previous SO question, the execution of the batch of these stored procedures pegs the CPU at 100% and continues on for hours before eventually failing. This leads me to want to create a single script that contains all the functionality of the stored procedures. Why you ask? Well, because it works. I would prefer to keep the logic in the stored procedure but until I can figure out why the stored procedures are so slow, and failing, I need to proceed with the "script" method.
So, what I am looking to do is to take all the stored procedures and find a way to "script" their functionality out to a single SQL script. I can use the "Tasks => Generate Scripts" wizard but the result contains all the Create Procedure and Begin and End functionality that I don't need.
In the versions of studio, etc. I use, there are options to control whether to script out the "if exists statements".
If you just want to capture the procs without the create statements, you could be able to roll your own pretty easily usig sp_helptext proc
For example, I created this proc
create proc dummy (
#var1 int
, #var2 varchar(10)
) as
begin
return 0
end
When I ran sp_helptext dummy I get pretty much the exact same thing as the output. Comments would also be included
I don't know of any tool that is going to return the "contents" without the create, as the formal parameters are part of the create or alter statement. Which probably leaves you using perl, python, whatever to copy out the create statement -- you lose the parameters -- though I suppose you could change those into comments.
Related
I have two separate procedures. One procedure alters the existing table with new columns. The other procedure adds data to the tables. They aren't being executed, only created. When I hit run, the procedure that adds data to the columns throws an error saying the column does not exist. I understand that it's not created because I didn't exec the procedure that contains the altered code. Not sure why the code inside the procedure executes since I thought that it only creates the procedure.
Some of the code is repetitive and I understand. This is simply to get a working solution before modifying it dynamically.
To answer this more fully than my comment - Stored procedures are compiled. So if you try and do something that is invalid, the compilation will fail. It is not only checked at runtime.
Try this and it will fail every time:
create table junk(a int)
create procedure p as
update junk set b=1
If you want this to work, run the procedure that creates the columns before you attempt to create the procedure that inserts the data, or change the insert procedure so that it uses dynamic sql
Note that if you're desperate to have a db that has no columns but has a procedure that references them for insert, you can create the columns, create the insert procedure and then drop the columns again. The procedure won't run because dropping the columns invalidated it, but it will still exist
Not quite sure why you'd want to though- db schema is very much a design time thing so the design should be evolutionary. If you're doing this as part of a wider work in a front end language, take a look at a database migratory tool - it's a device that runs scripts, typically on app startup, that ensures the db has all the columns and data the app needs for that version to run. It's bidirectional too, typically, so if you downgrade then the migratory will/can remove columns and data it added
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 recently joined one of the project in my team. They use ASP.NET MVC and MS SQL along with Entity Framework as ORM.
I noticed that each of the stored procedures used in the EF has this common line at the start of the stored procedure definitation
IF(0=1) SET FMTONLY OFF
I thought this was a very strange condition so I googled a bit about it and also asked my co workers about it. They say that when EF maps the stored procedure it send all parameters as null and skips all the if loop. Hence it would also skip the IF(0=1) condition and would then SET FMTONLY OFF
On searching for SET FMTONLY OFF MSDN, says
Returns only metadata to the client. Can be used to test the format of
the response without actually running the query.
It becomes a problem when you dont control the database, you have to keep telling the DBA's to add it and explain to them over and over again why is it needed in the first place.
I still dont have a clear idea why this is required. If someone can explain this a bit in detail or guide me to some link which has this topic covered would mean the world to me.
I believe the reason is similar to the one for stored procedures that run from SSRS. In summary, when FMTONLY is active, your stored procedure may have some unexpected results. Hence the reason for explicitly turning it off. For details read Dealing with the Evil of FMTONLY from SSRS
Having IF(0=1) SET FMTONLY OFF
seems like a risky thing to casually do in stored procedures read in by entity framework.
Entity Framework is the only source of this flag being set as a standard practice that I'm aware of (presumably other ORM's may use it).
the purpose (as I understand it) is to provide a way to get a procedures return schema without actually touching any data. (some stored procedures you don't want to execute just to update an orm's object model.
so unless you have a table that is counting the number of times your EF model has been updated (which might be interesting academically)
for additional information see
Stored procedure returns int instead of result set
the safest way to use ftmonly with entity framework (in my mind) is..
under the following circumstances
if the procedure in question is complex and confuses EF (EF reads the first returned schema, flow logic ignored)
let EF set the flag for you. (I clear it below to exit early)
use always false logic (which would be ignored when FTMONLY is on - interpret this as EF is trying to read schema)
at the beginning of the complex procedure do the following
if(0=1) -- if FMTONLY is on this if condition is ignored
begin
-- this loop will only be entered if fmtonly is on (ie EF schema read)
select
column1
,column2
...
,columnX
from whateverA
cross join whateverB
...
cross join whateverQ
-- joins don't matter but they might make it easier to get the column definitions
-- and names you desire. the important thing here is generating the proper
-- return schema... which is as complex as whatever you are trying to return
where 1=0
set FMTONLY off -- do this so that you can now force an early return since EF
-- usually only wants the first data set schema... other orms might
-- do something different
return -- this will be ignored if FMTONLY is still on
end
I have done this temporarily in order to be able to use the designer to map functions to represent the stored procedure in code. The problem is that the designer passes null by default to the procedure to determine the schema. This can sometimes be a problem with stored procs that do validation and throw exceptions etc if null is passed. The Setting you describe gets around this since it returns meta and not the actual data.
As far as I understand the scenarios, when an EDMX is updated, to return the result set instead of INT for a stored procedure, SET FMTONLY OFF is helpful.
For ex. "SELECT * FROM #tempTable" is written in a stored procedure,when an edmx is updated for this stored procedure, the type generated in Context.cs file for this stored procedure can be -
public virtual int SPName.
Ideally it must be:
public virtual ObjectResult SPName
To attain the above result, we have to use SET FMTONLY OFF.
We are avoiding the return type as INT and making it as type of resultset:
LINK to know how to use: http://www.sandeepknarware.in/?p=247
I have a single derived field that is populated by a series of update statements, each statement joining to a different table and different fields. It is important that the series of updates execute in a specific order, i.e. a join to table A may produce result X then a join to table B produces result Y in which case I want result Y. Normally I just create a series of Update statments in the appropriate order and store them either in a single SSIS SQL container or in a single stored procedure. Is there a best practice regarding using or not using a GO command or BEGIN END between these update statements?
Why do you think consecutive statements would be executed out of order? Do you have specific locking hints on any of the statements (e.g. UPDLOCK, HOLDLOCK, etc.)? Otherwise if you have two consecutive statements, A and B, and A changes something, B will see that change. How that works in SSIS may be different if you have some branching or multi-threading capabilities, but this is not possible in a stored procedure.
Also GO is not a T-SQL command, it is a batch separator recognized by certain client tools like Management Studio. If you try to put a GO between two statements in a stored procedure, one of two things will happen:
the procedure will fail to compile (if the opening BEGIN doesn't have a matching END right before the GO).
the procedure will compile (if there is no BEGIN/END wrapper), but it will be shorter than you thought, ending at the first GO rather than where you intended.
Statements are executed in exactly the order that you write them in. You don't need GO or BEGIN...END to ensure ordering. For that reason using either of these has no effect. They also have nothing to do with transactions.
I have an application that (unfortunately) contains a lot of its business logic is stored procedures.
Some of these return masses of data. Occassionally the code will need a small amount of the data returned from the stored procedure. To get a single clients name, I need to call a stored procedure that returns 12 tables and 950 rows.
I am not able (due to project politics) to change the existing stored procedures or create a replacement stored procedure - the original massive procedure must be called as that contains the logic to find the correct client. I can create a new procedure as long as it uses the original massive procedure.
Is there anyway I can get SQL server to return only a subset, (a single table, or even better a single row of a single table) of a stored procedure?
I have to support sql server 2000 +
It is not possible to conditionally modify the query behaviour of a procedure whose source code you cannot change.
However, you can create a new procedure that calls the original then trims down the result. A SQL 2000 compatible way of doing this might be:
declare #OriginalResult table (
// manually declare every column that is returned in the original procedure's resultset, with the correct data types, in the correct order
)
insert into #OriginalResult execute OriginalProcedure // procedure parameters go here
select MyColumns from #OriginalResult // your joins, groups, filters etc go here
You could use a temporary table instead of a table variable. The principle is the same.
You will definitely pay a performance penalty for this. However, you will only pay the penalty inside the server, you will not have to send lots of unnecessary data over the network connection to the client.
EDIT - Other suggestions
Ask for permission to factor out the magic find client logic into a separate procedure. You can then write a replacement procedure that follows the "rules" instead of bypassing them.
Ask whether support for SQL 2000 can be dropped. If the answer is yes, then you can write a CLR procedure to consume all 12 resultsets, take only the one you want, and filter it.
Give up and call the original procedure from your client code, but find a way of measuring the performance drop, so that you can exert some influence on the decision-making backed up with hard data.
No, you can't. A stored procedure is a single executable entity.
You have to create a new stored proc (to return what you want) or modify the current one (to branch) if you want to do this: project politics can not change real life
Edit: I didn't tell you this...
For every bit of data you need from the database, call the stored procedure each time and use the bit you want.
Don't "re-use" a call to get more data and cache it. After all, this is surely the intention of your Frankenstein stored procedure to give a consistent contract between client and databases...?
You can try to make SQL CLR stored procedure for handle all tables returned by your stored procdure and
in C# code to find data you need and return what you need. But I think that is just is going to make things more complicated.
When you fill your dataset with sored procedure which return more results sets in data set you get for each
result set one DataTable.