SQL Server 2008 modify system stored procedure - sql-server-2008

I have inherited maintenance of a SQL Server (2008), and I want to modify some of the system stored procedures. These are user-defined system stored procedures (for example: sys.sp_customproc). I can only assume they were created as system procedures so they could be shared across multiple databases? But regardless, I need to modify them.
Here is an example of one of them.
USE [msdb]
GO
/****** Object: StoredProcedure [sys].[sp_dbmmonitorhelpmonitoring] Script Date: 06/12/2013 13:16:52 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [sys].[sp_dbmmonitorhelpmonitoring]
as
begin
set nocount on
if (is_srvrolemember(N'sysadmin') <> 1 )
begin
raiserror(21089, 16, 1)
return (1)
end
declare #freq_type int, -- 4 = daily
#freq_interval int, -- Every 1 days
#freq_subday_type int, -- 4 = based on Minutes
#freq_subday_interval int, -- interval
#job_id uniqueidentifier,
#schedule_id int,
#retention_period int,
#jobname nvarchar( 256 )
select #jobname = isnull( formatmessage( 32047 ), N'Database Mirroring Monitor Job' )
select #job_id = job_id from msdb.dbo.sysjobs where name = #jobname
if (#job_id is null) -- if the job does not exist, error out
begin
raiserror( 32049, 16, 1 )
return 1
end
select #schedule_id = schedule_id from msdb.dbo.sysjobschedules where job_id = #job_id
select #freq_type = freq_type,
#freq_interval = freq_interval,
#freq_subday_type = freq_subday_type,
#freq_subday_interval = freq_subday_interval
from msdb.dbo.sysschedules where schedule_id = #schedule_id
-- If the frequency parameters are not what we expect then return an error
-- Someone has changed the job schedule on us
if (#freq_type <> 4) or (#freq_interval <> 1) or (#freq_subday_type <> 4)
begin
raiserror( 32037, 16, 1)
return 1
end
select #freq_subday_interval update_period
return 0
end
When I try to execute it, I get the error:
Msg 208, Level 16, State 6, Procedure sp_dbmmonitorhelpmonitoring, Line 46
Invalid object name 'sys.sp_dbmmonitorhelpmonitoring'.
My login is 'sa', I am mapped to the user 'dbo' in the [msdb] database. How do I modify this stored procedure?

You cannot alter a SP once you have marked it as a "system stored procedure". Instead, you have to drop it, recreate it and mark it as a system stored procedure again (using sp_ms_marksystemobject).
I'm sure you already realize how very dangerous it is to mess with anything that has been marked as "system". I feel obliged to strongly recommend that you make plenty of backups before you attempt any of this. Namely, back up: master, model and MSDB.

Related

Transaction error in stored procedure that is not using BEGIN or END TRANSACTION

I have a stored procedure "let's call it MY_NEW_SP" in which I'm not using BEGIN TRY / BEGIN CATCH. but, when I'm excecuting this SP (MY_NEW_SP), I get the following error:
Msg 266, Level 16, State 2, Procedure <MY_NEW_SP>, Line 132
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 0, current count = 1.
This new stored procedure makes a big select basically, no transactions are made "in the sense of make DML operations on tables (INSERT, DELETE, UPDATE)", but in temp tables "i.e. #tmp".
I'm thinking this transaction error is due I'm using SET XACT_ABORT ON; in other stored procedures, but, I'm not sure.
I follow what it is said here: C. Using TRY...CATCH with XACT_STATE
The basic structure of the stored procedure that uses SET XACT_ABORT ON; is as follows:
IF NOT EXISTS (SELECT * FROM sysobjects WHERE TYPE = 'P' AND NAME = 'PROCEP_NEW_SP' )
BEGIN
EXEC dbo.sp_executesql #statement = N'CREATE PROCEDURE PROCEP_NEW_SP AS'
END
GO
ALTER PROCEDURE PROCEP_NEW_SP
(
#ID_TABLE INT
)
AS
BEGIN
DECLARE #TBL_CONSECUTIVE TABLE ( LOG_CONSECUTIVE INT );
SET XACT_ABORT ON;
BEGIN TRANSACTION
BEGIN TRY
IF ISNULL(#ID_TABLE, -1) = -1
BEGIN
SET #ID_TABLE = 1;
DELETE FROM #TBL_CONSECUTIVE;
INSERT INTO T_BH_LOG_TABLE (ASO_NCODE, CHA_NCODE, TSO_NCODE,
MSO_DACTION_DATE, MSO_CRESULT, MSO_CCAUSE_FAILURE)
OUTPUT INSERTED.MSO_NCODE INTO #TBL_CONSECUTIVE
SELECT #ASO_NCODE, ISNULL(#CHA_NCODE, 1), ISNULL(#TSO_NCODE, 1),
GETDATE() AS MSO_DACTION_DATE, #CST_FAIL_OR_SUC, #CST_GENERIC_MSG;
IF (XACT_STATE()) = 1
BEGIN
COMMIT TRANSACTION;
END
SELECT NULL Id_table, 'Failed' Result_process, 'Parameter (ID_TABLE) is required.' Result_process_message;
RETURN;
END
-- Operation:
UPDATE MY_TABLE
SET NAME = 'SAMPLE'
WHERE ID_TABLE = #ID_TABLE;
IF (XACT_STATE()) = 1
BEGIN
COMMIT TRANSACTION;
END
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
INSERT INTO T_BH_LOG_TABLE (ASO_NCODE, CHA_NCODE, TSO_NCODE,
MSO_DACTION_DATE, MSO_CRESULT, MSO_CCAUSE_FAILURE)
OUTPUT INSERTED.MSO_NCODE INTO #TBL_CONSECUTIVE
SELECT 1 AS ASO_NCODE, 1, 1 As TSO_NCODE,
GETDATE() AS MSO_DACTION_DATE, #CST_FAIL_OR_SUC, #CST_GENERIC_MSG;
SELECT NULL Id_table, 'Failed' Result_process, 'Internal error. See log # (' + CAST(L.LOG_CONSECUTIVE AS NVARCHAR) + ') for more details.' Result_process_message;
FROM #TBL_CONSECUTIVE L;
RETURN;
END CATCH
END;
I really don't know if by using SET XACT_ABORT ON; is causing this kind of error.
Anyone can point me in the right direction for solve this issue?

getting wrong value of out param on mysql procedure

I created a procedure on mysql.
Here's my sql.
drop procedure if exists proc_serial_no;
DELIMITER //
CREATE PROCEDURE `proc_serial_no`(IN comp_code varchar(20), IN meat_rule_one varchar(20),OUT serial_no int)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY INVOKER
COMMENT 'serial no generator for trace code'
begin
declare current_no int default 0;
select serial_no into current_no from t_serial_no where comp_code = comp_code and rule = meat_rule_one;
if current_no = 0
then insert into t_serial_no (id,no,comp_code,rule) values ( replace(uuid(),'-',''),1,comp_code,meat_rule_one);
else update t_serial_no set no = no + 1 where comp_code = comp_code and rule = meat_rule_one;
end if;
select serial_no = current_no + 1;
end
I'm expecting the out param [serial_no] to increase every time I call the procedure,but it's always zero.
When I change sql related to the out param to
select no into serial_no from t_serial_no where comp_code = comp_code and rule = meat_rule_one;
It worked!
I could't figure out why. Anyone can answer this would be in great help!
This may be right or wrong. But it may be due to ,
Everytime you call the procedure , the local variable current_no is by its default value it is 0.
When the scope moves out of the procedure and again when you call that procedure, it again starts with its default value 0 again and again.
And also,
May be everytime you pass the value 0 to serial_no param everytime you call that procedure and it again starts with 0 everytime when the scope moves out and comes in.

Use trigger to filter certain date

I have a table called COURSE with these columns:
CourseId int
CourseName varchar
DateofStart Date
I would like to create a trigger which ensures that courses cannot be run during August.
Check the examples given in this site for writing the trigger
https://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm#i1025109
step 1: Since you need to check that courses cannot run during the august, you would be requiring a BEFORE INSERT trigger type.(Check the syntax in the link)
Step 2: Write the logic in Trigger body which will check the date that is being entered in the table
Step 3: If the DateofStart is in august raise an exception or process accordingly
Do try and share the code snippet.
Try this SQL code (for SQL Server)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER Tr_Course
ON Course
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF TRIGGER_NESTLEVEL() > 1
RETURN
UPDATE Course
SET dateOfStart = I.dateOfStart
FROM Course AS C
JOIN INSERTED I ON C.courseID = I.courseID
WHERE MONTH(I.dateOfStart) <> 8
END
GO
create trigger check_month
on COURSE
for Insert
as
declare #Date nvarchar(10)
declare #month int
select #Date=i.DateofStart from inserted i;
set #month= (select DATEPART(MONTH,#Date))
if(#month=8)
begin
Rollback
end
else
begin
commit
end

Run Stored Procedure From Another Database in Current Database

I have one shared database and multiple client databases. The data is stored in the client database. We want to create a master set of stored procedures in the shared database and execute them from the client database. Given the following:
use shared;
go
create procedure GetInvoices as
print db_name() ' <- current database'
select * from invoices
go
use client1;
create table invoices(...columns...)
exec shared.dbo.GetInvoices
This returns the following error:
shared <- current database
Msg 208, Level 16, State 1, Procedure GetInvoices, Line 3
Invalid object name 'invoices'.
Without using dynamic SQL, how can I run the stored procedure in shared from client1 so that it executes in client1 and thus has access to all of the tables in client1?
You can run a stored procedure defined in master database in context of client1 database and see all client1 database tables, without dynamic SQL, but it uses undocumented stored procedure sp_ms_marksystemobject.
Your stored procedure name must start with sp_, for example sp_GetInvoices. Create it in master database, then call exec sp_ms_marksystemobject sp_GetInvoices to make it see the tables of the current database.
USE master
GO
CREATE OR ALTER PROCEDURE sp_GetInvoices
AS
BEGIN
SELECT ClientName from Invoice
END
GO
exec sp_ms_marksystemobject sp_GetInvoices
USE client1
GO
create table Invoice (ClientName varchar(100))
insert Invoice select 'Acme Client'
exec sp_GetInvoices
Result (running on SQL Server version 13.0.5081.1):
ClientName
------------
Acme Client
Try this on your "Master" database:
CREATE PROCEDURE [dbo].[GetDataFromClient]
#DB VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #STMT VARCHAR( 300 );
DECLARE #SP VARCHAR( 500 );
SET #SP = 'dbo.GetData';
SET #STMT = 'EXEC(''' + #SP + ''')';
EXEC('USE '+ #db + ';' + #STMT)
END
Now on the "Client" database:
CREATE TABLE [dbo].[TestClient](
[ID] [int] NOT NULL,
[Description] [varchar](10) NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[ID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY].
Create the stored procedure to retrieve data from table TestClient
CREATE PROCEDURE [dbo].[GetData]
AS
BEGIN
SELECT *
FROM TestClient;
END
Now you can retrieve the columns from the TestClient Database using:
USE [TestMaster]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[GetDataFromClient]
#DB = N'TESTCLIENT'
SELECT 'Return Value' = #return_value
GO
You can call stored procedure using four part name after creating link server.
Or it can be called by openquery option.
LinkSerevr:
EXEC [ServerName] .dbname.scheme.StoredProcedureName
openquery : SELECT * FROM
OPENQUERY( [ServerName] .dbname.scheme.StoredProcedureName)

Stored Procedure (mysql) fails with "can't return a result set in the given context"

I'm trying to get this SP to return (leave) if some conditions fails and so forth.
This code validates and it saves the procedure, but when I call the procedure with:
CALL ACH_Deposit(30027616,3300012003,200.00,"USD", "127.0.0.1")
It fails with error: "Procedure can't return a result set in the given context"
Does anyone have any idea on what the error is?
Procedure code:
CREATE DEFINER=`redpass_web_urs`#`%` PROCEDURE `ACH_Deposit`(
IN __Account_ID BIGINT,
IN __To_Bank_Account BIGINT,
IN __Amount DECIMAL(10,2),
IN __Currency CHAR(3),
IN __IP_Address VARCHAR(50)
)
COMMENT 'Makes a ACH deposit'
BEGIN
-- Declare Account Parameters
DECLARE _Account_Status INT;
DECLARE __Transaction_ID INT;
DECLARE _Account_Type INT DEFAULT 0;
DECLARE _Fee INT;
SELECT
Account_Status AS _Account_Status,
Account_Type AS _Account_Type
FROM Account_Users
WHERE Account_ID = __Account_ID;
main: BEGIN
-- Step 1, is account active ?
IF _Account_Status <> 1 THEN
-- Account must be active (not restricted, closed etc)
SELECT Response_Code, Description FROM ResponseCodes WHERE Response_Code = 106;
LEAVE main; -- Here we die..
END IF;
-- Step 2, Calculate the FEE (Loading Funds with ACH)
IF _Account_Type = 1 THEN
-- Personal Account
SET _Fee = (SELECT Fee_Template_Personal_1 FROM Fees WHERE Fee_Type_ID = __Fee_Type_ID);
ELSE
-- Business Account
SET _Fee = (SELECT Fee_Template_Business_1 FROM Fees WHERE Fee_Type_ID = __Fee_Type_ID);
END IF;
-- Step 3, Check that Fee is not bigger then the actual amount
IF _Fee > __Amount THEN
SELECT Response_Code, Description FROM ResponseCodes WHERE Response_Code = 108;
LEAVE main; -- Here we die..
END IF;
-- If we come here, we can make the transactions
INSERT INTO Bank_Transaction
(Bank_Account_ID
,Transaction_Type
,Amount
,IP_Address
,Pending)
VALUES
(__To_Bank_Account
,11
,__Amount
,__IP_Address
,1); -- Reserverade pengar
-- Transaction ID
SET __Transaction_ID = (SELECT LAST_INSERT_ID());
-- Deduct the Fee
INSERT INTO Bank_Transaction
(Bank_Account_ID
,Transaction_Type
,Amount
,Fee_Type_ID
,Fee_Transaction_ID)
VALUES
(__To_Bank_Account
,4
,-__Fee
,21
,__Transaction_ID);
END main;
SELECT Response_Code, Description, __Transaction_ID AS Transaction_ID
FROM ResponseCodes
WHERE Response_Code = 1;
END
To retrieve multiple resultsets from the stored procs, you should use a client which supports multiple queries.
If you use PHP, use MySQLi extension and call the procedure using mysqli_multi_query.
MySQL extension is only able to retrieve the first recordset returned by the proc. To be able to use ti, you should set CLIENT_MULTI_RESULTS (decimal 131072) in the parameter $client_flags to mysql_connect