When I am designing table then I am putting text in description attribute of all column.
Suppose column name is empid and column description is Employee ID.
So I need to show the data from my table but want to show column name from description attribute which will querying sys table.
How is it possible? Can anyone give me a sample SQL?
You can show the extended property in addition to the values from the table (i.e., as another column), but not in lieu of the column name without using dynamic SQL. If you want to simply return the description with the data, you can do something like this:
Create Table dbo.Test
(
EmpId int not null Primary Key
, Col1 varchar(10) null
, Col2 varchar(10) null
)
Insert dbo.Test( EmpId, Col1, Col2 )
Select 1, 'Foo', 'Bar'
Union All Select 2, 'Gamma', 'Theta'
GO
EXEC sys.sp_addextendedproperty
#name = N'MS_Description',
#value = N'EmployeeID',
#level0type = N'SCHEMA', #level0name = dbo,
#level1type = N'TABLE', #level1name = Test,
#level2type = N'COLUMN', #level2name = EmpId;
GO
EXEC sys.sp_addextendedproperty
#name = N'MS_Description',
#value = N'Column1',
#level0type = N'SCHEMA', #level0name = dbo,
#level1type = N'TABLE', #level1name = Test,
#level2type = N'COLUMN', #level2name = Col1;
GO
EXEC sys.sp_addextendedproperty
#name = N'MS_Description',
#value = N'Column2',
#level0type = N'SCHEMA', #level0name = dbo,
#level1type = N'TABLE', #level1name = Test,
#level2type = N'COLUMN', #level2name = Col2;
GO
Select T.EmpId, ColDesc.Emp1Desc
, T.Col1, ColDesc.Col1Desc
, T.Col2, ColDesc.Col2Desc
From Test As T
Cross Apply (
Select Min( Case When objname = 'EmpId' Then value End ) As Emp1Desc
, Min( Case When objname = 'Col1' Then value End ) As Col1Desc
, Min( Case When objname = 'Col2' Then value End ) As Col2Desc
From fn_listextendedproperty (NULL, 'schema', 'dbo', 'table', 'Test', 'column', default)
) As ColDesc
If you wanted to just pull the descriptions, you can do that like so:
Select objname, value As Description
From fn_listextendedproperty (NULL, 'schema', 'dbo', 'table', 'Test', 'column', default)
Are you referring to extended properties? If so, you can query sys.extended_properties (see the previous link for more details).
Related
I have a C# WinForms application that manages stored procedures used by different services. What the users see is something like that:
exec stored_procedure_name param1, param2, param3
And since param1 doesn't mean anything to them (they can't see the stored procedure), I would like to present to them small descriptions of the parameters which are normally saved in the header of the stored procedure.
A typical stored procedure would like:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[stored_procedure_name]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[stored_procedure_name]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*************************************************************************************
[Procedure Info]
Author = myName
Description = this stored procedure returns results.
**************************************************************************************
[Parameters Info]
#param1 = this is parameter one
#param2 = this is parameter two
#param3 = this is parameter three
**************************************************************************************
[Changes]
2015-06-17 The stored procedure is optimized.
*/
CREATE PROCEDURE [dbo].[stored_procedure_name]
#param1 int,
#param2 nvarchar(20),
#param3 nvarchar(10)
AS
BEGIN
-- SP code here
END
GO
From the above, I want to get the descriptions in the Parameters info. I know that I can use the following SQL to retrieve the stored procedure as text/table:
CREATE TABLE #tmpHeader
(
TEXT NVARCHAR(1000)
)
INSERT INTO #tmpHeader
EXEC sp_helptext 'stored_procedure_name';
SELECT * FROM #tmpHeader
DROP TABLE #tmpHeader
Any ideas or suggestions how to proceed from here in order to get the content of the parameters info?
I am also open to any other suggestions.
Consider using extended properties to store meta-data. This is much cleaner than parsing the module text.
EDIT:
The example below returns all parameters plus descriptions for those parameters with extended properties. In your code, you can pass the schema and object names as parameters instead of the local variables used here for illustration.
EXEC sp_addextendedproperty #name = N'Description',
#value = 'this is parameter one', #level0type = N'Schema',
#level0name = 'dbo', #level1type = N'Procedure',
#level1name = 'stored_procedure_name', #level2type = N'Parameter',
#level2name = '#param1';
GO
EXEC sp_addextendedproperty #name = N'Description',
#value = 'this is parameter two', #level0type = N'Schema',
#level0name = 'dbo', #level1type = N'Procedure',
#level1name = 'stored_procedure_name', #level2type = N'Parameter',
#level2name = '#param2';
GO
EXEC sp_addextendedproperty #name = N'Description',
#value = 'this is parameter three', #level0type = N'Schema',
#level0name = 'dbo', #level1type = N'Procedure',
#level1name = 'stored_procedure_name', #level2type = N'Parameter',
#level2name = '#param3';
GO
DECLARE
#SchemaName sysname = 'dbo'
, #ObjectName sysname = 'stored_procedure_name';
SELECT properties.objtype
, properties.objname
, parms.name
, properties.value
FROM sys.parameters AS parms
LEFT JOIN fn_listextendedproperty('Description', 'Schema', #SchemaName, 'Procedure',
#ObjectName, 'Parameter', DEFAULT) AS properties ON
properties.objname COLLATE DATABASE_DEFAULT = parms.name
WHERE
parms.object_id = OBJECT_ID(QUOTENAME(#SchemaName) + '.' + QUOTENAME(#ObjectName));
GO
This should make the think your looking for.
SELECT SUBSTRING(definition,CHARINDEX(N'[Parameters Info]',definition),CHARINDEX(N'[',definition,CHARINDEX(N'[Parameters Info]',definition)+1)-CHARINDEX(N'[Parameters Info]',definition))
FROM sys.sql_modules
WHERE object_id = OBJECT_ID('YOUR PROCEDURE!!!')
It searches for Parameters Info and goes any further until if finds another header block (beginning with [). You can also specify that it should search for *.
SQl Server 2008 R2 - I have a trigger that's set up to send an email to a specific email address that is monitored by a third party system which sends out messages to certain groups of people based upon the subject of that message. The limitation to this is that only one group number can be in the subject per message. But I need to send the same message from the trigger to at least two groups meaning that two separate emails must be generated with two different subject lines. I'm thinking possibly a cursor in the trigger would accomplish this but I'm not sure how to write it.
So in the code below I have #cat in which I need to send an email with the subject 'ED' EVERY time the trigger kicks off. I then need to send another email with the subject being set based on the condition of the case statement currently used to set the subject line. I've updated the code as follows and by removing the scalar variables have moved to a set based trigger(??) I've also created and inserted the information into an "email" table that will have a service set up to run every 10 sec and email all records that are set as 0 and then update the flag to 1.
New Code -
CREATE TABLE [dbo].[tb_BatchEmail] (
[BatchEmailID] [bit] NOT NULL DEFAULT 0
,[To] [varchar](50) NOT NULL DEFAULT 'someemail' --will never change
,[Body] [varchar](255) NULL
,[Subject] [varchar](20) NOT NULL
,[Profile] [varchar](50) NOT NULL DEFAULT 'Alert' --will never change
,[OrderID] [varchar] (25) NULL
,[OrderDateTime] [datetime] NULL
,[SentDateTime] [datetime] NULL
,CONSTRAINT msg_pk PRIMARY KEY CLUSTERED (BatchEmailID)
) ON [PRIMARY]
GO
ALTER TRIGGER [dbo].[VeOrders] ON [dbo].[Orders]
FOR INSERT
AS
SELECT #visitid = i.VisitID
,#priority = Priority
,#cat = Category
,#procedure = OrderedProcedureName
,#orderid = OrderID
,#orderdate = OrderDateTime
,#locationid = CurrentLocationID
,#roomid = CASE
WHEN RoomTreatmentID IS NULL
THEN 'No Room#'
ELSE RoomTreatmentID
END
FROM inserted i
INNER JOIN livedb.dbo.EdmPatients edp
ON edp.VisitID = i.VisitID
WHERE Priority = 'STAT'
AND Category IN ('CT', 'MRI', 'XRAY', 'US', 'NUC', 'ECHO')
AND CurrentLocationID = 'ED'
IF #cat IN ('CT', 'MRI', 'XRAY', 'US', 'NUC', 'ECHO')
AND #priority = 'STAT'
AND #locationid = 'ED'
BEGIN
DECLARE #msg VARCHAR(500)
DECLARE #subject VARCHAR(500)
SET #msg = #roomid + '-' + #procedure + '-' + #priority + '.' --+ 'Order DateTime/Number ' + #order + '/+ #locationid + ' ' + #orderid
SET #subject = CASE
WHEN #cat = 'US'
THEN 'Test Ultra Sound'
WHEN #cat = 'CT'
THEN 'Test C T'
WHEN #cat = 'XRAY'
THEN 'Test X-Ray'
END
INSERT INTO livedb.dbo.tb_BatchEmail (
Body
,[Subject]
,OrderID
,OrderDateTime
)
SELECT Body = #msg
,[Subject] = #subject
,OrderID = #orderid
,OrderDateTime = #orderdate
END
Old Code -
ALTER TRIGGER [dbo].[VeOrders] ON [dbo].[Orders]
FOR INSERT
AS
IF NOT EXISTS (
SELECT *
FROM dbo.EdmPatients
WHERE CurrentLocationID = 'ED'
)
RETURN
DECLARE #priority VARCHAR(50)
DECLARE #cat VARCHAR(50)
DECLARE #procedure VARCHAR(50)
DECLARE #orderid VARCHAR(50)
DECLARE #locationid VARCHAR(10)
DECLARE #roomid VARCHAR(10)
DECLARE #visitid VARCHAR(50)
SELECT #visitid = VisitID
,#priority = Priority
,#cat = Category
,#procedure = OrderedProcedureName
,#orderid = OrderID
,#locationid = CurrentLocationID
,#roomid = CASE
WHEN RoomTreatmentID IS NULL
THEN 'No Room#'
ELSE RoomTreatmentID
END
FROM inserted i
INNER JOIN dbo.EdmPatients edp
ON edp.VisitID = i.VisitID
WHERE Priority = 'STAT'
AND Category IN ('CT', 'MRI', 'XRAY', 'US', 'NUC', 'ECHO')
AND CurrentLocationID = 'ED'
IF #cat IN ('CT', 'MRI', 'XRAY', 'US', 'NUC', 'ECHO')
AND #priority = 'STAT'
AND #locationid = 'ED'
BEGIN
DECLARE #msg VARCHAR(500)
DECLARE #subject VARCHAR(500)
SET #msg = #roomid + '-' + #procedure + '-' + #priority + '.'
SET #subject = CASE
WHEN #cat = 'CT'
THEN '55194'
WHEN #cat = 'US'
THEN '59843'
WHEN #cat = 'XRAY'
THEN '70071'
END
EXEC msdb.dbo.sp_send_dbmail
#recipients = N'someemail'
,#body = #msg
,#subject = #subject
,#profile_name = 'Alerts'
END
I would separate out the concerns from creating the emails and sending them. Have a service whose only job is to send emails. Emails are abstract in that they all have a From, a To, a Body, and a Subject. Create a table (named BatchEmail for example) that holds all of those fields.
Then your trigger is simple. It just inserts into your BatchEmail table in a normal select statement.
insert into BatchEmail
(To, Body, Subject, Profile)
select N'someemail',
#msg,
CASE
WHEN #cat = 'CT'
THEN '55194'
WHEN #cat = 'US'
THEN '59843'
WHEN #cat = 'XRAY'
THEN '70071'
END,
'Alerts'
Your BatchEmail table should have some column or flag indicating when or if it was sent.
Your service (or even the Insert Trigger on the table, if you really love triggers) Could just select 1 row at a time that hasn't been processed.
while true
begin
select top 1
#BatchEmailID = batchEmailID,
#To = to,
#From = from,
#Body = body,
#Subject = subject,
#ProfileName = ProfileName
from BatchEmail
where processed = 0
if(#BatchEmailID is null)
break;
exec msdb.dbo.sp_send_dbmail #To, #Body, #Subject, #ProfileName
update BatchEmail
set processed = 1
where BatchEmailID = #BatchEmailID
end
If you still would rather not have a separate service and insist on doing all of this in the trigger, you could turn #BatchEmail into a table variable, still with a #Processed bit column and select 1 row at a time, updating #Processed after each row.
The questions really says it all, Is it possible to update an extended property of a column in a table. I have been looking around online but they only seem to show updating the extended property for a table and not the columns in a table.
EXECUTE sp_updateextendedproperty
N'MS_Description',
#v,
N'SCHEMA', N'dbo',
N'TABLE', N'Table_1',
N'COLUMN', N'i'
It's actually the very first sample in MSDN topic:
http://technet.microsoft.com/en-us/library/ms186885.aspx
Here's a more complete sample:
--Add extended property
EXEC sp_addextendedproperty
#name = N'Question1'
,#value = N'Hello'
,#level0type = N'Schema', #level0name = dbo
,#level1type = N'Table', #level1name = Acceptance
,#level2type = N'Column', #level2name = P101;
GO
--Verify
SELECT * FROM fn_listextendedproperty
(NULL, 'schema', 'dbo', 'table', 'Acceptance', 'column', 'P101');
GO
--Update the extended property.
EXEC sp_updateextendedproperty
#name = N'Question1'
,#value = N'Hello, What is your name'
,#level0type = N'Schema', #level0name = dbo
,#level1type = N'Table', #level1name = Acceptance
,#level2type = N'Column', #level2name = P101;
GO
--Verify
SELECT * FROM fn_listextendedproperty
(NULL, 'schema', 'dbo', 'table', 'Acceptance', 'column', 'P101');
GO
I'm passing parameters to a stored procedure from an asp.net webform.
However, for one particular combination of parameters a single parameter appear to being ignored.
The parameters I'm passing that are causing the issue are as follows:
EXEC #return_value = [dbo].[spProgressCohorts]
#StuYear = N'10',
#DataCollection = N'March 2013 Teacher Assessments',
#SubjectName = N'English',
#TeachingGroup = N'Select All',
#Subgroup = N'Select All',
#KS2 = '',
#Result = ''
When I run the stored procedure with these parameters the results return as though the #Result variable is being ignored.
The results the stored procedure return are (the ks2en and result columns are included for reference):
surname forename ks2en result
El Hajj Zeinab D
Grzelak Marlena F+
Sage Nigel
However, I get just get Nigel Sage's record (as expected and this is what should be returned by the stored procedure) when when I run the following query:
select surname, forename, ks2en, result
from student join subject on subject.upn=student.upn
where datacollection='March 2013 Teacher Assessments' and stuyear='10' and name='english' and result='' and ks2en=''
My stored procedure is massive, so I'll just include code specific to the parameters above:
ALTER PROCEDURE [dbo].[spProgressCohorts]
#StuYear varchar(2),
#DataCollection varchar(100),
#SubjectName varchar(100),
#TeachingGroup varchar(30),
#Subgroup varchar(10),
#Result varchar(4),
#KS2 varchar(4)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
--interfering with SELECT statements.
SET NOCOUNT ON;
SELECT Forename + ' ' + Surname
FROM student
JOIN subject
ON subject.upn = student.upn
WHERE
(#StuYear = [stuyear]
AND #TeachingGroup = 'Select All'
AND [DataCollection] = #DataCollection
AND [Name] = #SubjectName
AND #Subgroup='Select All'
AND #KS2 = CASE #subjectName WHEN 'English' THEN KS2en WHEN 'Mathematics' THEN KS2ma ELSE KS2av END
AND [Result] like #Result + '%')
OR
(#StuYear = [stuyear]
AND #TeachingGroup Not Like 'Select All'
AND [DataCollection] = #DataCollection
AND [Name] = #SubjectName
AND [TeachingGroup] = #TeachingGroup
AND #Subgroup='Select All'
AND #KS2 = CASE #subjectName WHEN 'English' THEN KS2en WHEN 'Mathematics' THEN KS2ma ELSE KS2av END
AND [Result] like #Result + '%')
ORDER BY surname, forename
How about this?
...
AND [Result] LIKE CASE #Result WHEN '' THEN '' ELSE #Result + '%' END)
I have created a wrapper stored procedure to create publication for transactional replication for SQL Server 2008 Standard Edition SP3. But when I execute the procedure I get the following error. The column "file_exists" is not user defined. This error doesn't make any sense to me. This works on Dev environment but same code doesn't work on test environment. Dev and Test are identical as far as I can tell. I also tried to explicitly set options, made them 5496 (SELECT ##OPTIONS). Any help greatly appreciated.
-- error
Msg 50000, Level 16, State 1, Procedure CreatePublicationForDB, Line 161
Invalid column name 'file_exists'.
-- Begin Script
CREATE DATABASE TestPublication
GO
USE TestPublication
CREATE TABLE Orders(
OrderID INT PRIMARY KEY,
CustomerID INT,
ProductID INT,
UpdatedAt DATETIME,
UpdatedBy DATETIME
)
GO
CREATE TABLE Products(
ProductID INT PRIMARY KEY,
ProductName VARCHAR(100)
)
GO
CREATE VIEW V_Order
AS
SELECT o.OrderID,o.CustomerID, p.ProductName
FROM Orders o
JOIN Products p
ON o.ProductID = p.ProductID
GO
CREATE SCHEMA repl
GO
CREATE TABLE repl.ReplicationTables
(
DBName sys.sysname NOT NULL DEFAULT('TestPublication'),
SchemaOwner sys.sysname NOT NULL DEFAULT('dbo'),
TableName sys.sysname NOT NULL
)
GO
INSERT INTO repl.ReplicationTables (tablename)
VALUES('Orders'),('Products'),('V_Order')
GO
USE TestPublication
GO
CREATE PROCEDURE CreatePublicationForDB( #databaseName sysname, #publicationName sysname = #databaseName, #allow_initialize_from_backup NVARCHAR(5) = 'true')
AS
BEGIN
BEGIN TRY
SET ANSI_WARNINGS ON
SET ANSI_PADDING ON
SET ANSI_NULLS ON
SET ARITHABORT ON
SET QUOTED_IDENTIFIER ON
SET ANSI_NULL_DFLT_ON ON
SET CONCAT_NULL_YIELDS_NULL ON
DECLARE #sp_replicationdboption varchar(MAX) = ' USE '+#databaseName +';',
#sp_addpulication VARCHAR(MAX) = ' USE '+#databaseName +';',
#sp_addpublication_snapshot VARCHAR(MAX) = ' USE '+#databaseName +';',
#sp_addarticle VARCHAR(MAX) = ' USE '+#databaseName +';',
#sp_startpublication_snapshot VARCHAR(MAX) = ' USE '+#databaseName +';'
DECLARE #allow_anonymous NVARCHAR(5) = CASE WHEN #allow_initialize_from_backup = 'false' OR #allow_initialize_from_backup IS NULL THEN 'true' ELSE 'false' END
DECLARE #immediate_sync NVARCHAR(5) = #allow_anonymous, #publisher sysname = ##SERVERNAME
-- set up database publication
SET #sp_replicationdboption += '
exec sp_replicationdboption #dbname = N'''+#databaseName+ ''',
#optname = N''publish'',
#value = N''true'''
-- Publication
SET #sp_addpulication += '
exec sp_addpublication #publication = N'''+#publicationName+ ''',
#description = N''Transactional publication of database '+#databaseName+' from Publisher '+#publisher+''',
#sync_method = N''concurrent'',
#retention = 0,
#allow_push = N''true'',
#allow_pull = N''true'',
#allow_anonymous = N'''+#allow_anonymous+ ''' ,
#enabled_for_internet = N''false'',
#snapshot_in_defaultfolder = N''true'',
#compress_snapshot = N''false'',
#ftp_port = 21,
#ftp_login = N''anonymous'',
#allow_subscription_copy = N''false'',
#add_to_active_directory = N''false'',
#repl_freq = N''continuous'',
#status = N''active'',
#independent_agent = N''true'',
#immediate_sync = N'''+#immediate_sync+ ''' ,
#allow_sync_tran = N''false'',
#autogen_sync_procs = N''false'',
#allow_queued_tran = N''false'',
#allow_dts = N''false'',
#replicate_ddl = 1,
#allow_initialize_from_backup = N'''+COALESCE(#allow_initialize_from_backup, 'false')+ ''' ,
#enabled_for_p2p = N''false'',
#enabled_for_het_sub = N''false'''
IF #allow_initialize_from_backup = 'false'
BEGIN
-- publication snapshot
SET #sp_addpublication_snapshot +='
exec sp_addpublication_snapshot #publication = N'''+#publicationName+ ''',
#frequency_type = 1,
#frequency_interval = 0,
#frequency_relative_interval = 0,
#frequency_recurrence_factor = 0,
#frequency_subday = 0,
#frequency_subday_interval = 0,
#active_start_time_of_day = 0,
#active_end_time_of_day = 235959,
#active_start_date = 0,
#active_end_date = 0,
#job_login = null,
#job_password = null,
#publisher_security_mode = 1'
SET #sp_startpublication_snapshot+=' exec sys.sp_startpublication_snapshot #publication = N'''+#publicationName+ ''''
END
-- Articles
IF OBJECT_ID('tempdb..#t') IS NULL
BEGIN
PRINT 'creating temp table t'
CREATE TABLE #t (NAME sysname,objectid INT, sch_owner sysname NULL, article sysname NOT NULL, isIndexed BIT NULL, IsSchemaBound BIT NULL, TYPE CHAR(2) NULL)
END
INSERT INTO #t(NAME,objectid, sch_owner,isIndexed,IsSchemaBound, TYPE,article)
EXEC('
USE '+#databaseName + '
SELECT f.Name, f.object_id,f.sch, f.IsIndexed,f.IsSchemaBound, f.type,CASE WHEN ROW_NUMBER() OVER (PARTITION BY f.name ORDER BY f.sch) > 1 THEN f.name + CAST((ROW_NUMBER() OVER (PARTITION BY f.name ORDER BY f.sch) - 1) AS VARCHAR(2)) ELSE f.name END AS Article
FROM(
SELECT t.Name, t.object_id,t.sch, IsIndexed,IsSchemaBound, type
FROM
(SELECT DBName, SchemaOwner, TableName
FROM TestPublication.repl.ReplicationTables
GROUP BY DBName, SchemaOwner, TableName )rt JOIN
(SELECT o.Name, o.object_id,s.name AS sch, objectproperty(o.object_id, ''IsIndexed'') AS IsIndexed,objectproperty(o.object_id, ''IsSchemaBound'') AS IsSchemaBound, o.type
FROM
sys.objects o
JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE o.type IN (''U'',''V'')
AND ObjectProperty(o.object_id, ''IsMSShipped'') = 0
AND (ObjectProperty(o.object_id, ''TableHasPrimaryKey'') = 1 OR ObjectProperty(o.object_id, ''TableHasPrimaryKey'') IS NULL)
) t ON rt.tablename = t.name AND rt.SchemaOwner = t.sch
WHERE rt.DBName = '''+#databaseName + '''
) f'
)
SELECT #sp_addarticle +=
'exec sp_addarticle
#publication = N''' +#databaseName +
''', #article = N''' +t.article+
''', #source_owner = N''' +t.sch_owner +
''', #source_object = N''' + t.NAME +
''', #type = N''' +
CASE WHEN t.type = 'U' THEN 'logbased'
WHEN t.type = 'V' AND (IsIndexed = 1 OR IsSchemaBound = 1 )THEN 'indexed view schema only'
WHEN t.type = 'V' AND IsIndexed = 0 THEN 'view schema only' END
+''', #description = null,#creation_script = null,#pre_creation_cmd = N''drop'',
#schema_option = '+
CASE WHEN t.type = 'U' THEN '0x000000000803509F'
WHEN t.type = 'V' THEN '0x0000000008000001' END+
',#destination_table = N'''+t.Name+
''',#destination_owner = N'''+t.sch_owner+''''+
CASE WHEN t.TYPE = 'U' THEN
', #identityrangemanagementoption = N''manual'',#vertical_partition = N''false'',
#ins_cmd = N''CALL sp_MSins_'+t.sch_owner+''+t.Name+
''', #del_cmd = N''CALL sp_MSdel_'+t.sch_owner+''+t.Name+''',
#upd_cmd = N''SCALL sp_MSupd_'+t.sch_owner+''+t.Name+''''
ELSE ''
END
+';'
FROM #t t
PRINT 'Now running sp_replicationdboption'
PRINT #sp_replicationdboption
EXEC(#sp_replicationdboption)
PRINT 'Now running sp_addpulication'
PRINT #sp_addpulication
EXEC(#sp_addpulication)
IF #allow_initialize_from_backup = 'false'
BEGIN
PRINT 'Now running sp_addpulication_snapshot and starting snapshot'
PRINT #sp_addpublication_snapshot
EXEC(#sp_addpublication_snapshot)
EXEC(#sp_startpublication_snapshot)
END
PRINT 'Now running sp_addarticles'
PRINT #sp_addarticle
EXEC(#sp_addarticle)
-- exec sp_droppublication #publication = N'Products'
END TRY
BEGIN CATCH
IF ##trancount > 0
ROLLBACK
DECLARE #ERROR_SEVERITY INT, #ERROR_STATE INT, #ERROR_MESSAGE NVARCHAR(4000)
SELECT #ERROR_SEVERITY = ERROR_SEVERITY(), #ERROR_STATE = ERROR_STATE(), #ERROR_MESSAGE = ERROR_MESSAGE()
RAISERROR(#ERROR_MESSAGE, #ERROR_SEVERITY, #ERROR_STATE)
END CATCH
END
GO
and finally execute
EXEC CreatePublicationForDB 'TestPublication'
-- drop replication in case you want to run the above again.
exec TestPublication.dbo.sp_droppublication #publication = 'TestPublication'
exec TestPublication.dbo.sp_replicationdboption #dbname = 'TestPublication', #optname = 'publish', #value = 'false'
-- cleanup database
DROP DATABASE TestPublication
Sorry, old post I know, but I ran into a very similar situation and got around it. I haven't found a workable solution anywhere else. I'm including my experience to help others.
Summary of my situation is that I have an msbuild process running a series of scripts from a manifest file (text file with a series of script names) within a transaction. The scripts that were intended to create and configure agent jobs always died with the same error. (invalid column name "file_exists")
Procs used in my failing script(s):
msdb.dbo.sp_add_category
msdb.dbo.sp_add_job
msdb.dbo.sp_add_jobstep
msdb.dbo.sp_update_job
msdb.dbo.sp_add_jobschedule
msdb.dbo.sp_add_jobserver
Commenting out the call to msdb.dbo.sp_add_jobstep allowed the script to complete.
I do have SQL command variables in the form #database_name=N'$(DatabaseName)' in the script as well. This led to some misdirected efforts to try to use escape macros as mentioned in the "Important" note under [ #command= ] 'command' on the documentation for sp_add_jobstep.
https://msdn.microsoft.com/en-us/library/ms187358.aspx
If I run the build up to, but not including, the job creation script and start over, it succeeds.
What I found, after much trial and error, was that, even though the procs are qualified as being in [MSDB], unless I actually included a USE statement, the process fails. By beginning the script with "USE [MSDB] GO" and then switching back to my build target (i.e. USE [MyBuildDB] GO), I no longer get the error.
My agent jobs create as expected, and several scripts within the build run without error.
It's hard to say what the problem is without seeing all of the code and having the schema. I'd recommend not creating a wrapper to create publication(s). The create publication scripts can be saved and executed on demand when needed - eliminating the need for a wrapper.