SQL stored procedure change logging trigger not saving all text - sql

I created a stored procedure to log changes made to stored procedures. The issue is that the larger ones aren't being saved in their entirety and are being chopped off.
I need to be able to save the entire procedure text and it is also used as a means of reverting the a previous revision.
The trigger:
/****** Object: DdlTrigger [StoredProcUpdateInsert] Script Date: 12/05/2015 14:05:05 ******/
DROP TRIGGER [StoredProcUpdateInsert] ON DATABASE
GO
/****** Object: DdlTrigger [StoredProcUpdateInsert] Script Date: 12/05/2015 14:05:05 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [StoredProcUpdateInsert]
ON DATABASE
FOR CREATE_PROCEDURE, ALTER_PROCEDURE
AS
BEGIN
SET NOCOUNT ON
DECLARE #data XML
SET #data=EVENTDATA()
INSERT INTO dbo.ProcedureChanges
( ProcName ,
ProcText ,
ModifiedBy ,
DateTimeLastUpdated
)
VALUES ( #data.value('(/EVENT_INSTANCE/ObjectName)[1]','nvarchar(max)') , -- ProcName - nvarchar(450)
(SELECT TOP 1 text FROM syscomments WHERE id=OBJECT_ID(#data.value('(/EVENT_INSTANCE/ObjectName)[1]','nvarchar(max)'))) , -- ProcText - nvarchar(max)
#data.value('(/EVENT_INSTANCE/LoginName)[1]','nvarchar(max)') , -- ModifiedBy - nvarchar(250)
GETDATE() -- DateTimeLastUpdated - datetime
)
END
GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ENABLE TRIGGER [StoredProcUpdateInsert] ON DATABASE
GO

According to this article: https://msdn.microsoft.com/en-us/library/ms186293.aspx you shouldn't use syscommentsand instead should use sys.sqlmodules
The definition of syscomments.textfrom the article above says it's defined as nvarchar(4000). Presumably this means any DDL longer than 4000 characters is truncated and therefore you're only getting the first 4000 characters in your log table.
I haven't tested this but you could try:
INSERT INTO dbo.ProcedureChanges
( ProcName ,
ProcText ,
ModifiedBy ,
DateTimeLastUpdated
)
VALUES ( #data.value('(/EVENT_INSTANCE/ObjectName)[1]','nvarchar(max)') , -- ProcName - nvarchar(450)
(SELECT Definition FROM sys.sql_modules WHERE object_id=OBJECT_ID(#data.value('(/EVENT_INSTANCE/ObjectName)[1]','nvarchar(max)'))) , -- ProcText - nvarchar(max)
#data.value('(/EVENT_INSTANCE/LoginName)[1]','nvarchar(max)') , -- ModifiedBy - nvarchar(250)
GETDATE() -- DateTimeLastUpdated - datetime
)

Related

How to add header comments when altering stored procedures in SQL Server

I have a stored procedure where there are no header comments. I want to add them, but whenever I try, it is not included.
In SQL Server Management Studio I :
1.Right-click my stored procedure and click modify
USE [ABigDB]
GO
/****** Object: StoredProcedure [dbo].[spDoWork] Script Date: 21/08/2015 14:11:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spDoWork]
#Id uniqueidentifier,
#Session nvarchar(50),
#XMLData xml
WITH EXECUTE AS OWNER
AS
BEGIN
--etc etc...
END
2.I paste comments above the stored procedure and run the script :
-- Stored Procedure
-- Author: Dave
-- Create date: 21/08/2015
-- Description: Does Stuff
-- Change history
-- 07/08/2015 - Overlord - Done stuff
-- 06/08/2015 - Kerrigan - Done more stuff
USE [ABigDB]
GO
/****** Object: StoredProcedure [dbo].[spDoWork] Script Date: 21/08/2015 14:11:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spDoWork]
#Id uniqueidentifier,
#Session nvarchar(50),
#XMLData xml
WITH EXECUTE AS OWNER
AS
BEGIN
--etc etc...
END
3.When I modify the same stored procedure it appears as :
USE [ABigDB]
GO
/****** Object: StoredProcedure [dbo].[spDoWork] Script Date: 21/08/2015 14:11:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spDoWork]
#Id uniqueidentifier,
#Session nvarchar(50),
#XMLData xml
WITH EXECUTE AS OWNER
AS
BEGIN
--etc etc...
END
So how do I get the comments to appear there?
I solved it by doing the following:
USE [ABigDB]
GO
/****** Object: StoredProcedure [dbo].[spDoWork] Script Date: 21/08/2015 14:11:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- Stored Procedure
-- Author: Dave
-- Create date: 21/08/2015
-- Description: Does Stuff
-- Change history
-- 07/08/2015 - Overlord - Done stuff
-- 06/08/2015 - Kerrigan - Done more stuff
ALTER PROCEDURE [dbo].[spDoWork]
#Id uniqueidentifier,
#Session nvarchar(50),
#XMLData xml
WITH EXECUTE AS OWNER
AS
BEGIN
--etc etc...
END
Consider using the meta data in addition to your procedures, tables, columns, etc. for documentation purposes.
See the following that helps when reviewing your db objects.
Is it possible to add a description/comment to a table in Microsoft SQL 2000+

debugging stored procedure in MS SQL server 2008

I have a stored procedure and I'm trying to debug it in the query window... when I open the stored procedure, I set some breakpoints in the code, but they never get hit.. In the code below, I can step through the USE line, then set ANSI_NULLS ON and then the code just says commands executed successfully, even though I have breakpoints set all throughout the code below it. Am I missing something?!
USE [Tool1]
GO
/****** Object: StoredProcedure [dbo].[aspdnsf_ImportProductPricing_XML] Script Date: 10/02/2014 09:38:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Alter proc [dbo].[aspdnsf_ImportProductPricing_XML]
#pricing ntext
AS
BEGIN
SET NOCOUNT ON
CREATE TABLE #tmp (ProductID int, VariantID int, KitItemID int, Name nvarchar(400), KitGroup nvarchar(800), SKU nvarchar(50), SKUSuffix nvarchar(50), ManufacturerPartNumber nvarchar(50), Cost money, MSRP money, Price money, SalePrice money, Inventory int)
DECLARE #hdoc int, #retcode int
EXEC #retcode = sp_xml_preparedocument
#hdoc OUTPUT,
#pricing
INSERT #tmp
SELECT *
FROM OPENXML(#hdoc, '/productlist/productvariant', 2)
WITH (ProductID int, VariantID int, KitItemID int, Name nvarchar(400), KitGroup nvarchar(800), SKU nvarchar(50), SKUSuffix nvarchar(50), ManufacturerPartNumber nvarchar(50), Cost money, MSRP money, Price money, SalePrice money, Inventory int)
UPDATE dbo.ProductVariant
SET Price = t.Price,
SalePrice = nullif(t.SalePrice,0),
Inventory = t.Inventory,
Cost = t.cost
FROM dbo.ProductVariant p
join #tmp t on p.ProductID = t.ProductID and p.VariantID = t.VariantID
WHERE KitItemID = 0
UPDATE dbo.KitItem
SET PriceDelta = t.Price
FROM dbo.KitItem k
join #tmp t on k.KitItemID = t.KitItemID
WHERE t.KitItemID > 0
exec sp_xml_removedocument #hdoc
DROP TABLE #tmp
END
When you debug store procedure you have to prepare exec statement for that procedre. You set breakpoint on it and then use Run button to start debugging. When you step into the procedure new window will be opened. In that window set breakpoints. They will work.
I gave up on debug in SQL years ago, and am sad to hear it has not improved in even the most recent versions. Here’s an overview of the tatcic I use when debugging stored procedures, which may or may not help you.
First, cut-and-paste the code to a new “working” window.
Run any necessary special formatting commands, e.g.
USE [Tool1]
GO
/****** Object: StoredProcedure [dbo].[aspdnsf_ImportProductPricing_XML] Script Date: 10/02/2014 09:38:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Next, comment out everything down through the create (or alter) procedure statement, like so:
--USE [Tool1]
--GO
--/****** Object: StoredProcedure [dbo].[aspdnsf_ImportProductPricing_XML] Script Date: 10/02/2014 09:38:17 ******/
--SET ANSI_NULLS ON
--GO
--SET QUOTED_IDENTIFIER ON
--GO
--Alter proc [dbo].[aspdnsf_ImportProductPricing_XML]
-- #pricing ntext
If there are parameters, plop down a DECLARE statement in front of them, and remove any output settings.
Replace the AS statement with SET values for each parameter, and use these to set testing values
From there, scroll down through a portion of code, highlight that point and all preceding text (shift + control + home), and execute (F5), and observe what happens. Insert PRINT and SELECT statements and repeat as necessary, slowly increasing how much code gets executed with each call, or when possible running only a few selected lines of code.
There are of course a zillion gotchas to this (which is why it would be really nice to have real world debug in SQL—and I don’t see this happening, in part because of #Temp tables, and in part because of BEGIN TRANSACTION / EXECUTE / GOTO lunch / ROLLBACK), but I digress. One such gotcha here is your #Temp table. On the first pass it gets created, and on all subsequent passes you’ll get a “table already exists” error. Lazy (because it doesn't work the first time you run it) work-around:
DROP TABLE #tmp
CREATE TABLE #tmp (ProductID int, <etc>)
Fussy work-around:
IF object_id('tempdb..#Tmp') is not null
DROP TABLE #tmp
CREATE TABLE #tmp (ProductID int)
sp_xml_preparedocument / sp_xml_removedocument is going to be another gotcha. Not sure how to deal with that, we gave that up for Xquery years ago.

how to create a sp that inserts values from one table to another

Hi I want to create a stored procedure that takes specific values from one table and inserts them into another if a specific table been 'DateAquired ' is null I have this stored procedure below but it doesn't seem as expected please help.
Thanks in advance
this is my code
USE [MediaPlayer]
GO
/****** Object: StoredProcedure [dbo].[sp_Wishlists] Script Date: 11/26/2013 11:43:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[sp_Wishlists]
-- Add the parameters for the stored procedure here
#Name nvarchar (250),
#FileName nvarchar (250),
#FilePath nvarchar (50),
#FileSize float,
#DateAdded date,
#MediaLength nvarchar (50),
#MediaSubType nvarchar(50),
#MediaType nvarchar(50),
#Thumbnail image,
#DateAquired nvarchar (50),
#WishList int output ,
#CName nvarchar (50)output ,
#Media nvarchar (50)output,
#WishListID int output
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Select GeneralID, Name, FileName, FilePath,FileSize,DateAdded,MediaLength,MediaSubType,MediaType, Thumbnail,DateAquired As Wishlist
From General where NULLIF(DateAquired,'')IS Null
insert into Wishlists (generalID ,MediaType, Name)
values ((IDENT_CURRENT('dbo.General')),(IDENT_CURRENT('dbo.General')),(IDENT_CURRENT('dbo.General')))
SET #WishListID = ##IDENTITY
select GeneralID, MediaSubType, Name
From General where NOT EXISTS (Select Name from WishLists Where Name =#Name);
END
try below insert statement
insert into Wishlists (generalID ,MediaType, Name)
select GeneralID, MediaSubType, Name
From General where NOT EXISTS (Select Name from WishLists Where Name =#Name);

Invalid Object Name - Stored Procedure

I am creating a stored procedure in SQL Server via SSMS.
I have written the stored procedure below, however when I click execute it am given the error:
Msg 208, Level 16, State 6, Procedure NewQuestion, Line 11
Invalid object name 'hgomez.NewQuestion'.
the table is ownership is correct. (hgomez.Questions)
USE [devworks_oscar]
GO
/****** Object: StoredProcedure [hgomez].[NewQuestion] Script Date: 10/23/2011 23:55:08 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [hgomez].[NewQuestion]
(
#QUESTIONNAME nvarchar(50),
#QUESTION_ID int OUTPUT
)
AS
/* SET NOCOUNT ON */
INSERT INTO [Questions] (QuestionText) VALUES (#QUESTIONNAME)
SET #QUESTION_ID = SCOPE_IDENTITY();
RETURN
Thanks in advance
I was a fan of always prepending my CREATE statements with an explicit check for existence and dropping if it was found.
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'NewQuestion' AND ROUTINE_SCHEMA = 'hgomez')
BEGIN
DROP PROCEDURE hgomez.NewQuestion
END
GO
-- this is always a CREATE
CREATE PROCEDURE [hgomez].[NewQuestion]
(
#QUESTIONNAME nvarchar(50),
#QUESTION_ID int OUTPUT
)
AS
/* SET NOCOUNT ON */
INSERT INTO [Questions] (QuestionText) VALUES (#QUESTIONNAME)
SET #QUESTION_ID = SCOPE_IDENTITY();
RETURN
That can be a bit of hassle with regard to permissions so others use an approach wherein they create a stub method only to immediately ALTER it.
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'NewQuestion' AND ROUTINE_SCHEMA = 'hgomez')
BEGIN
EXEC ('CREATE PROCEDURE hgomez.NewQuestion AS SELECT ''stub version, to be replaced''')
END
GO
-- This is always ALTER
ALTER PROCEDURE [hgomez].[NewQuestion]
(
#QUESTIONNAME nvarchar(50),
#QUESTION_ID int OUTPUT
)
AS
/* SET NOCOUNT ON */
INSERT INTO [Questions] (QuestionText) VALUES (#QUESTIONNAME)
SET #QUESTION_ID = SCOPE_IDENTITY();
RETURN
This script tries to modify a procedure that already exists; it doesn't create the procedure.
To create the procedure use CREATE PROCEDURE
CREATE PROCEDURE [hgomez].[NewQuestion]
Once the procedure exists, you can modify its definition by using ALTER PROCEDURE
ALTER PROCEDURE [hgomez].[NewQuestion]
This solution https://stackoverflow.com/a/26775310/2211788 explained
If you drop and re-create a stored procedure it gets a new objectid - the list of stored procedures in SSMS is linked to the id it knows at the time the list was built. If you re-create it but don't refresh the stored procedures folder then any attempts to edit it will indicate the procedure is not found as the id has changed.
This happened to me once when I had two instances of SSMS open and I was working on the one I opened first. Closed them both down, reopened and it worked fine.

Stored procedure parses correctly but will not execute. Invalid object name. Msg 208

I've scripted up a stored procedure as follows. It will parse without errors, but when I try to execute it, it will fail. The error message reads: Msg 208, Level 16, State 6, Procedure aspnet_updateUser, Line 23
Invalid object name 'dbo.aspnet_updateUser'.
Here is the stored procedure.
USE [PMRS2]
GO
/****** Object: StoredProcedure [dbo].[aspnet_updateUser] Script Date: 05/25/2009 15:29:47 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[aspnet_updateUser]
-- Add the parameters for the stored procedure here
#UserName nvarchar(50),
#Email nvarchar(50),
#FName nvarchar(50),
#LName nvarchar(50),
#ActiveFlag bit,
#GroupId int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE dbo.aspnet_Users
SET UserName = #UserName, LoweredUserName = LOWER(#UserName), Email = #Email, FName = #FName, LName = #LName, ActiveFlag = #ActiveFlag, GroupId = #GroupId
WHERE LoweredUserName = LOWER(#UserName)
END
Looks like it might not exist yet, swap the Alter to a Create.
To avoid this happening in the furture, do what we do, never use alter proc. Instead we check for the existance of the proc and drop it if it exists, then create it with the new code:
IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'myProc')
BEGIN
DROP Procedure myProc
END
GO
CREATE PROCEDURE myProc
(add the rest of the proc here)
Here is another solution
USE [PMRS2]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID ( 'dbo.YourProcedureName', 'P' ) IS NOT NULL
DROP PROCEDURE dbo.YourProcedureName;
GO
CREATE PROCEDURE [dbo].[YourProcedureName] (
#UserName varchar(50),
#Password varchar(50))
AS
BEGIN
SET NOCOUNT ON;
select ... (your query)
END