I'm doing investigation of code repo and find one thing that make me confused. SQL Server stored procedures are contained in a repo as a set of queries with following structure:
IF OBJECT_ID(N'[dbo].[sp_ProcTitle]', N'P') IS NULL
BEGIN
EXEC dbo.sp_executeSQL N'CREATE PROCEDURE [dbo].[sp_ProcTitle] AS dummy:;';
END
ALTER PROCEDURE dbo.sp_ProcTitle
#ParamOne int,
#ParamTwo date,
#ParamThree int
AS
SET NOCOUNT ON
-- some procedure body
END
Never before I saw AS dummy:; and now I'm a little confused, I can't find any good explanation what is it and how it works. Could anybody tell me what does it mean this statement? How it works? What is the reason to have it? Any thought would be good to hear. Or, please, advise me some link where I can find good explanation.
This is simply a label, such that could be used in a GOTO statement.
The word "dummy" is unimportant. It's simply trying to create the stored procedure if it doesn't exist, with a minimal amount of text. The content is then filled in with the ALTER.
Conceivably, the dummy text could later be searched for to see if any procedures were created and didn't have their content filled in, to check against failed deployments, etc.
Why do this? Well, it preserve the creation time of the stored procedure in metadata (which can be useful in administration or tracking down problems), and is compatible with versions of SQL Server that lack the CREATE OR ALTER... support.
This might make a little more sense if we add a little formatting to the CREATE:
CREATE PROCEDURE [dbo].[sp_ProcTitle]
AS
dummy:
This is, effectively, an empty procedure with a label called dummy. The user appears to be using this to ensure that the procedure exists first, and the ALTERing it. In older versions of SQL Server, such methods were needed because it didn't support CREATE OR ALTER syntax. As such, if you tried to ALTER a procedure that didn't exist the statement failed, and likewise if you try to CREATE a procedure that already exists it fails.
If you are on a recent version of SQL Server, I'd suggest changing to CREATE OR ALTER and getting rid of the call to sys.sp_executesql.
Related
i have a situation where i want to check a certain column ( like version number) and then apply a bunch of ddl changes
trouble is i am not able to do it with in a IF BEGIN END block, since DDL statements require a GO separator between them, and TSQL wont allow that.
I am wondering if there is any way around to accomplish this
You don't need to use a full block. A conditional will execute the next statement in its entirety if you don't use a BEGIN/END -- including a single DDL statement. This is equivalent to the behavior of if in Pascal, C, etc. Of course, that means that you will have to re-check your condition over and over and over. It also means that using variables to control the script's behavior is pretty much out of the question.
[Edit: CREATE PROCEDURE doesn't work in the example below, so I changed it to something else and moved CREATE PROCEDURE for a more extended discussion below]
If ((SELECT Version FROM table WHERE... ) <= 15)
CREATE TABLE dbo.MNP (
....
)
GO
If ((SELECT Version FROM table WHERE... ) <= 15)
ALTER TABLE dbo.T1
ALTER COLUMN Field1 AS CHAR(15)
GO
...
Or something like that, depending on what your condition is.
Unfortunately, CREATE/ALTER PROCEDURE and CREATE/ALTER VIEW have special requirements that make it much harder to work with. They are pretty much required to be the only thing in a statement, so you can't combine them with IF at all.
For many scenarios, when you want to "upgrade" your objects, you can work it as a conditional drop followed by a create:
IF(EXISTS(SELECT * FROM sys.objects WHERE type='p' AND object_id = OBJECT_ID('dbo.abc')))
DROP PROCEDURE dbo.abc
GO
CREATE PROCEDURE dbo.abc
AS
...
GO
If you do really need conditional logic to decide what to do, then the only way I know of is to use EXECUTE to run the DDL statements as a string.
If ((SELECT Version FROM table WHERE... ) <= 15)
EXECUTE 'CREATE PROC dbo.abc
AS
....
')
But this is very painful. You have to escape any quotes in the body of the procedure and it's really hard to read.
Depending on the changes that you need to apply, you can see all this can get very ugly fast. The above doesn't even include error checking, which is a royal pain all on its own. This is why hordes of toolmakers make a living by figuring out ways to automate the creation of deployment scripts.
Sorry; there is no easy "right" way that works for everything. This is just something that TSQL supports very poorly. Still, the above should be a good start.
GO is recognised by client tools, not by the server.
You can have CREATEs in your stored procedures or ad-hoc queries with no GO's.
Multiple "IF" statements? You can test then for the success of subsequent DDL statements
Dynamic SQL? EXEC ('ALTER TABLE foo WITH CHECK ADD CONSTRAINT ...')?
As mentioned, GO is a client only batch separator to break down a single SQL text block into batches that are submitted to the SQL Server.
I am going to use dynamic sql in my stored procedure to remove some of the code duplication. But I see one big drawback for me in this case: I have rather big DB with lots of objects. My stored procedure is using few tables and since it is compiled I can find dependencies easily from Sql Server management studio.But when I rewrite it to dynamically build some of the repeating queries I will loose dependency possibility and next time when I would need to find who is using this table I will need to do raw text search in my code repository rather than asking sql server for dependency. This is probably small concern, but I would still like to try to find solution.
So my question is: is there anything I can do to still have ability to see what dependencies my stored proc has? Like declare some dependencies upfront etc?
You can get dependencies to show up for the stored procedure for sections of code that never execute. For example, if you wanted to "declare" a dependency on a table named TestTable, you could use
CREATE PROC MyStoredProc
AS
DECLARE #SQL VarChar(4000)
SET #SQL = 'SELECT * FROM TestTable'
EXEC (#SQL)
RETURN
SELECT 0 FROM TestTable -- Never executes but shows as dependency
END
I have below SP:
CREATE PROCEDURE [dbo].[ups_Ins_TblA] #ID int, #Comment nvarchar(max) AS
BEGIN
SET NOCOUNT ON
INSERT INTO [db_assets].[Claim]
(ID,Comment)
Values
(#ID,#Comment)
END
Basically, my question is, is there a way to call this in BCS Sharepoint(Business Connectivity Service) using out-of-the-box functionality? Can I further adjust the SP so that it can be supported with all 'CRUD' operations? Pls suggest ideas?
Note: I have made the table as simple as possible.
I don't want to make a straight-insert from the table because I have to join this to another table where document resides that's why I want to use SP.
I'd been spending almost 2-3days reading and still going on.. If anyone can direct me to the light, pls help? Thank you so much!!
This is a noob mistake. Apologies.
The answer is to write your stored procedure separately and assign it the each operation accordingly (Read Item, read List, Create, Update, Delete).
Yes, there will be 5 sp.
As long as the mapping of identifier is set appropriately, the creation of Lists will not have issue (with CRUD operation enabled).
I have observed the following feature when I rename a stored procedure.
sp_RENAME 'User_Validate', 'sp_UserValidate'
And when I do sp_helptext sp_UserValidate the procedure's name that i see is
CREATE PROCEDURE User_Validate
(#userEmail nvarchar(200),
#userPassword nvarchar(32))....
Why doesn't the name get updated in the stored procedure?
But when I check
select * from sys.procedures
I find the name field being updated? What's the reason behind it? The only logical conclusion I can draw is it's better to drop the procedure and recreate with a new name.
edit 1:
If I do sp_helptext User_Validate it returns "The object 'User_Validate' does not exist in database 'Process' or is invalid for this operation." But when I view the stored procedure the name User_Validate is still there.
Note: I know that renaming stored procedures is not a good practice, the question I asked is out of curiosity.
sp_helptext does not reverse engineer the procedure, it simply shows the original T-SQL batch that created the procedure, including comments and white spaces.
sp_rename is not recommended for renaming stored procedures, views, triggers, and user defined functions
Your conclusion is right, you should drop and re-create it with a new name. The same is stated in BOL - Rename a Stored Procedure
You should also check the dependencies of a stored procedure because renaming a stored procedure may cause dependent objects to fail if they are not updated to match the change
Hope this helps
So, not sure what is happening. But I have stored procedure and it keeps disappearing out of my DB in SQL 2k.
I can add it again and then try to execute it from my web app and i get an exception saying the stored procedure cant be found. So then ill go back to management and refresh and its gone again !?!
here is the config for the stored proc:
set ANSI_NULLS OFF
set QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[USP_Equipment_Delete]
#EquipmentID int
AS
DELETE FROM [dbo].[Equipment]
WHERE
[EquipmentID] = #EquipmentID
None of my other stored procedure disappear. This is the only one. I have easily 100 in there. They all use the same SQLHelper class. This one just keeps disappearing!!!??!!
Any help or suggestions are appreciated!
Thanks so much!
You were creating this or another stored proc and at the end of your code, maybe after a comment, where you did not see it you have a drop of this proc.
Take a look at your db using:
select syo.name
from syscomments syc
join sysobjects syo on
syo.id = syc.id
where syc.[text] like '%DROP PROC%'
I had the same problem and I just fixed it:
In the script file it was missing the "GO" statement between the end of the stored procedure and the beginning of the next "IF EXIST THEN DROP" statement.
So what happened was that the drop statement was getting appended to the end of whatever stored procedure was above it in the script. So when the software ran the stored procedure it would drop whatever stored procedure was below it in the script.
It seems so obvious to us now but didn't make any sense at the time. We found it running the SQL profiler against a customer's database that was having the problem in the field.
Are you using the correct database?
Try
using [database name]
prior to executing your stored procedure, just to make sure.
Do you have a CREATE PROCEDURE anywhere? You can't ALTER a procedure if it doesn't exist.
Perhaps the code to access the stored procedure is using a different context other than dbo. Make sure to add dbo.USP_Equipment_Delete to the code using it.
I was facing the problem that all Stored Procedures with a create statement disappeared from the database after execution.
The Solution was: The database user should have the rights to drop,create and alter on the database in which the "Stored Procedures" are going to be created.
Perhaps there's a job thats restoring an old backup periodically?
Check if the "Initial Catalog" in your connection string is set to the correct database.
Put the database in single user mode (and make sure you're the single user) and check if the procedure still disappears every hour?
If it's there, then this query must return a record:
SELECT * FROM sysobjects
WHERE id = OBJECT_ID('USP_Equipment_Delete')
AND OBJECTPROPERTY(id, N'IsProcedure') = 1