Run stored procedure then email results - sql-server-2008

I am trying to run a stored procedure in SQL Server 2008, then email the results of the stored procedures but am getting the following error:
Msg 22050, Level 16, State 1, Line 0
Error formatting query, probably invalid parameters
Msg 14661, Level 16, State 1, Procedure sp_send_dbmail, Line 504
Query execution failed: Msg 102, Level 15, State 1, Server XXYYZZ, Line 1
Incorrect syntax near '#returnvalue'.
Here is some sample code to replicate:
CREATE PROCEDURE pTestEmail
AS
-- Create the result table - Stores the results of the stored procedure --
DECLARE #returnvalue TABLE (
ClientID varchar(5)
);
BEGIN
SET NOCOUNT ON;
-- Insert some fake data --
INSERT INTO #returnvalue
VALUES ('001'),
('002'),
('003'),
('004'),
('005');
-- Test that the fake data is in there
-- Uncomment the next line to see it works --
-- SELECT * FROM #returnvalue;
-- Email the results in the #returnvalue table --
EXEC msdb.dbo.sp_send_dbmail
#execute_query_database='MainDB',
#recipients=N'me#null.com',
#body='Message Body',
#subject ='The Resultset',
#profile_name ='Reports',
#query ='SELECT * #returnvalue',
#attach_query_result_as_file = 1,
#query_attachment_filename ='Results.txt'
END
GO
I've tested the DBmail function and have gotten it to work correctly. Can you use an # scalar in the stored procedure like I am doing, or do I need to use a global temp table?

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?

How to capture JSON data from a stored procedure for testing with tSQLt

I'm trying to use tSQLt to test a stored procedure that returns JSON data. The database is running under SQL Server 2016. The stored procedure is as follows (simplified considerably):
CREATE PROCEDURE [SearchForThings]
#SearchText NVARCHAR(1000),
#MaximumRowsToReturn INT
AS
BEGIN
SELECT TOP(#MaximumRowsToReturn)
[Id],
[ItemName]
FROM
[BigTableOfThings] AS bt
WHERE
bt.[Tags] LIKE N'%' + #SearchText + N'%'
ORDER BY
bt.[ItemName]
FOR JSON AUTO, ROOT(N'Things');
END;
This can't be tested in the same way XML can - I've tried a test table, as below, which was suggested in this related answer here -
CREATE TABLE #JsonResult (JsonData NVARCHAR(MAX))
INSERT #JsonResult (JsonData)
EXEC [SearchForThings] 'cats',10
The above code produces this error:
The FOR JSON clause is not allowed in a INSERT statement.
I cannot alter the stored procedure under test. How can I capture the JSON result?
Without being able to modify the stored proc, your last ditch effort would be to use OPENROWSET. Here's how you would call it in your case:
INSERT INTO #JsonResult
SELECT *
FROM OPENROWSET('SQLNCLI', 'Server=[ServerNameGoesHere];Trusted_Connection=yes;','EXEC SearchForThings ''cats'',10')
If you get an error, you can use the following to enable ad hoc distributed queries:
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
I know this is two years on but I stumbled on this today when trying to solve a different tSQLt problem.
Your issue occurs because the column being returned from your stored procedure is not explicity named. If you provide a column name for the JSON data you can insert the data into a #temp table, e.g.:
create table BigTableOfThings (
Id int not null,
ItemName nvarchar(50) not null,
Tags nvarchar(50) not null
);
insert BigTableOfThings values
(1, 'Whiskers', 'Cool for Cats'),
(2, 'Barkley', 'Dogs Rule!');
GO
create procedure SearchForThings
#SearchText nvarchar(1000),
#MaximumRowsToReturn int
as
begin
select [JsonData] = (
select top(#MaximumRowsToReturn)
Id,
ItemName
from
BigTableOfThings as bt
where
bt.Tags like N'%' + #SearchText + N'%'
order by
bt.ItemName
for json auto, root(N'Things')
);
end
go
create table #JsonResult (JsonData nvarchar(max));
insert #JsonResult (JsonData)
exec SearchForThings 'cats',10;
select * from #JsonResult;
go
Which yields...
{"Things":[{"Id":1,"ItemName":"Whiskers"}]}

openrowset is giving error "OLE DB provider "SQLNCLI10" for linked server "(null)" returned message "Deferred prepare could not be completed."

I have a table which is passed into stored procedure. now i want to insert stored procedure results in temp table #b using 'select * into #b from openrowset. My sql code is as follows:
create type add1 as table
(score int)
alter proc qwe123
#table add1 readonly
as
begin
select score,score + 2 as cal
from #table
end
go
declare #t add1
insert into #t
select score
from abc
select * into #b from
openrowset('sqlncli','server=localhost;trusted_connection=yes','exec qwe123 #t')
Can someone tell me why am I getting error as :
OLE DB provider "SQLNCLI10" for linked server "(null)" returned message "Deferred prepare could not be completed.".
Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "#t".
You have to declare your variable #t with the execution statement:
openrowset('sqlncli','server=localhost;trusted_connection=yes',
'DECLARE #t add1 = 1 exec qwe123 #t')

SQL Stored Procedure unknown Error

I am writing a SQL stored procedure that will be called in Access. My sp will be passed four data fields(BatchID, InstrumentName, FileName,QueueId). Then it will insert a record into a table (tblinstrumentInterfaceLog). Here is my code thus far:
CREATE PROCEDURE upInsertToInstrumentInterfaceLog #BatchID int, #InstrumentName nvarchar(60), #FileName nvarchar(60), #QueueID int
INSERT INTO tblInstrumentinterfaceLog (batchId,Instrumentname,"Filename",QueueID,DateOfBatch,folder)
VALUES (#batchid,#InstrumentName,#FileName,#QueueID,#getdate(),'New')
GO
I believe I have the correct format but I get two errors:
Msg 156, Level 15, State 1, Procedure upInsertToInstrumentInterfaceLog, Line 2
Incorrect syntax near the keyword 'INSERT'.
Msg 137, Level 15, State 2, Procedure upInsertToInstrumentInterfaceLog, Line 3
Must declare the scalar variable "#QueueID".
To Make sure there wasn't perhaps a datatype issue I looked at the schema of tblInstrumentInterfaceLog and this it seemed to match the way I initialized each.
Could someone tell me if they see an issues with this stored procedure
You need an AS after your parameter declarations and your #getdate() command is just getdate()
CREATE PROCEDURE upInsertToInstrumentInterfaceLog
#BatchID int, #InstrumentName nvarchar(60), #FileName nvarchar(60), #QueueID int
AS
BEGIN
INSERT INTO tblInstrumentinterfaceLog (batchId,Instrumentname,"Filename",QueueID,DateOfBatch,folder)
VALUES (#batchid,#InstrumentName,#FileName,#QueueID,
getdate(),'New')
END
GO
You forgot the AS
CREATE PROCEDURE upInsertToInstrumentInterfaceLog #BatchID int, #InstrumentName nvarchar(60),
#FileName nvarchar(60), #QueueID int
AS
INSERT INTO tblInstrumentinterfaceLog (batchId,Instrumentname,"Filename",QueueID,DateOfBatch,folder)
VALUES (#batchid,#InstrumentName,#FileName,#QueueID,#getdate(),'New')
GO

SQL Server 2008 modify system stored procedure

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.