I have a basic query, and i'd like to email the results. How can I do this at the query level? So if my query is:
SELECT
Store_Id, Paid_Out_Amount, Paid_Out_Comment,
Paid_Out_Datetime, Update_UserName
FROM Paid_Out_Tb
WHERE (Store_Id = 1929) OR
(Paid_Out_Amount > 50) AND
(Paid_Out_Datetime BETWEEN
CONVERT(DATETIME, '2012-06-01 00:00:00', 102) AND
CONVERT(DATETIME, '2012-06-30 00:00:00', 102))
How would I email the output? I have a procedure to send email via SMTP and the parameters are #From, #To, #Subject and #body... which works.. How would I make the body the outcome of the query?
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[sp_SQLNotify]
#From varchar(100) ,
#To varchar(100) ,
#Subject varchar(100)=" ",
#Body varchar(4000) = "Test"
/*********************************************************************
This stored procedure takes the above parameters and sends an e-mail.
All of the mail configurations are hard-coded in the stored procedure.
Comments are added to the stored procedure where necessary.
Reference to the CDOSYS objects are at the following MSDN Web site:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_messaging.asp
***********************************************************************/
AS
Declare #iMsg int
Declare #hr int
Declare #source varchar(255)
Declare #description varchar(500)
Declare #output varchar(1000)
--************* Create the CDO.Message Object ************************
EXEC #hr = sp_OACreate 'CDO.Message', #iMsg OUT
--***************Configuring the Message Object ******************
-- This is to configure a remote SMTP server.
-- http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_schema_configuration_sendusing.asp
EXEC #hr = sp_OASetProperty #iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendusing").Value','2'
-- This is to configure the Server Name or IP address.
-- Replace MailServerName by the name or IP of your SMTP Server.
EXEC #hr = sp_OASetProperty #iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpserver").Value', '10.1.1.10'
-- Save the configurations to the message object.
EXEC #hr = sp_OAMethod #iMsg, 'Configuration.Fields.Update', null
-- Set the e-mail parameters.
EXEC #hr = sp_OASetProperty #iMsg, 'To', #To
EXEC #hr = sp_OASetProperty #iMsg, 'From', #From
EXEC #hr = sp_OASetProperty #iMsg, 'Subject', #Subject
-- If you are using HTML e-mail, use 'HTMLBody' instead of 'TextBody'.
EXEC #hr = sp_OASetProperty #iMsg, 'TextBody', #Body
EXEC #hr = sp_OAMethod #iMsg, 'Send', NULL
-- Sample error handling.
IF #hr <>0
select #hr
BEGIN
EXEC #hr = sp_OAGetErrorInfo NULL, #source OUT, #description OUT
IF #hr = 0
BEGIN
SELECT #output = ' Source: ' + #source
PRINT #output
SELECT #output = ' Description: ' + #description
PRINT #output
END
ELSE
BEGIN
PRINT ' sp_OAGetErrorInfo failed.'
RETURN
END
END
-- Clean up the objects created.
EXEC #hr = sp_OADestroy #iMsg
PRINT 'Mail Sent!'
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
This is the procedure i'm using to send the mail... which works... I just want to add a spot in it to send the results of the query above it... Can this be done easily within in the procedure?
Use the SQL Server Powershell pack. An example (with detailed explanation) of using it to obtain output is here.
(The above is taken from this SO answer, but to clarify something s/he says: SQL Server 2008 client components is required (Express should be fine), but it can work with SQL Server 2000 databases (source).)
You can also use a variable for a direct loop concatenation. See https://stackoverflow.com/a/4447564/1180926 (although you would use tab and newline delimiters instead of HTML code).
You would then just change your query accordingly, store it in #Body, and you're done!
Related
I am trying to extract a blob file from SQL Server. I was able to get it to execute successfully but when I look in my Desktop\consol\output directory, the file isn't there (refreshed, still nothing). Here is the code:
SELECT * FROM FileWarehouse
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
DECLARE #SQLIMG VARCHAR(MAX),
#File VARBINARY(MAX),
#OpPath VARCHAR(MAX),
#ObjectToken INT
SELECT #File = StoredFile FROM [dbo].[FileWarehouse] WHERE Id= 157994
SET #OpPath = 'C:\Users\Nick\Desktop\consol\output\marksheet.doc'
EXEC sp_OACreate 'ADODB.Stream', #ObjectToken OUTPUT
EXEC sp_OASetProperty #ObjectToken, 'Type', 1
EXEC sp_OAMethod #ObjectToken, 'Open'
EXEC sp_OAMethod #ObjectToken, 'Write', NULL, #File
EXEC sp_OAMethod #ObjectToken, 'SaveToFile', NULL, #OpPath, 2
EXEC sp_OAMethod #ObjectToken, 'Close'
EXEC sp_OADestroy #ObjectToken
GO
In the SELECT statement, dbo.[FileWarehouse] and StoredFile are both underlined, saying 'Invalid Object Name' and 'Invalid Column Name', respectively. They are definitely valid, so I'm not sure it's saying that. Here is the tutorial I was following https://www.youtube.com/watch?v=8g7_F3Ice6E .
Any help would be greatly appreciated. Thank You.
While Dan's answer is correct (use Powershell or SQL CLR instead), the reason your COM automation isn't working, is that you've failed to capture and inspect the return codes from the extended stored procedures.
Here's an example:
--exec sp_configure 'Show Advanced Options', 1
--reconfigure
--exec sp_configure 'Ole Automation Procedures', 1
--reconfigure
declare #url varchar(2000) = 'http://www.bing.com'
declare #hr int;
declare #win int;
begin try
EXEC #hr=sp_OACreate 'WinHttp.WinHttpRequest.5.1',#win OUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win, 'Open',NULL,'GET',#url,'false'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win,'Send'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
declare #status int
EXEC #hr=sp_OAGetProperty #win,'Status', #status out
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
if #status <> 200
begin;
declare #msg varchar(2000) = concat('web request failed ', #status);
throw 60000, #msg, 1;
end;
declare #response table(text nvarchar(max));
insert into #response(text)
EXEC #hr=sp_OAGetProperty #win,'ResponseText';
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win;
select * from #response;
EXEC #hr=sp_OADestroy #win
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win;
end try
begin catch
EXEC #hr=sp_OADestroy #win
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win;
throw;
end catch
The IntelliSense error is erroneous if the script runs.
I suggest you generally avoid the ole automation procs for new development. If you don't really need to use T-SQL to create the file, consider a simple PowerShell script. This is more robust and flexible for ad-hoc needs. Below is an example that uses the standard ADO.NET objects.
$connection = New-Object System.Data.SqlClient.SQLConnection("Data Source=YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI")
$command = New-Object System.Data.SqlClient.SqlCommand("SELECT StoredFile FROM [dbo].[FileWarehouse] WHERE Id= 157994;", $connection)
$connection.Open()
$blob = $connection.ExecuteScalar()
$connection.Close()
[System.IO.File]::WriteAllBytes("C:\Users\Nick\Desktop\consol\output\marksheet.doc", $blob)
We have an instance where an old vb6 dll needs to be implemented and forces us to use sp_OACreate and sp_OAMethod. Given that the code will be inside a transaction, does anyone know whether or not the rollback will work for the code in that assembly? The assembly will access and make changes to the data.
Or will the sp_OAMethod call and the db code inside the assembly create it's own independent session outside of the transaction?
Thank you.
begin tran
declare #hr int
declare #Object int
declare #Return int
declare #Output varchar(255)
exec #hr= sp_OACreate 'DIssues32.Iclass',#object out
IF #hr <> 0
BEGIN
EXEC sp_Getoaerrorinfo #object, #hr,#output out
select #output
END
else
begin
exec #hr = sp_OAMethod #object,'Transfer', #Return , #LOCATION_NAME,
#TO_LOCATION_NAME, #QTY_REQUESTED, #SYSUSER_ID, '', #CONNSTRING, True, '', False, True
IF #hr <> 0
BEGIN
EXEC sp_Getoaerrorinfo #object, #hr,#output out
select #output
rollback
END
exec #hr= sp_OADestroy #object out
print #return
end
commit
You have to use sp_bindsession for the second connection (from VB6 component) to join the main lock space and share the transaction.
You can use sp_getbindtoken to get the token and pass it along the connection string but obviously the VB6 code will have to be tweaked to bind the session if token is found at the end of #CONNSTRING
I am writing a procedure take the data from the web service. The web services gives the data in an XML string. However, It is truncating the data being pulled from the website. It runs perfectly when executed in SSMS. It truncated the data to 2048 characters when run through a batch file and truncated the data to 512 characters when run using a SS Job.
These values can not be random. There must be a setting somewhere but I can't find it. Any ideas?
Here's the code:
DECLARE
#url nvarchar(max),
#win integer,
#hr integer ,
#Date date,
#SearchDate nvarchar(50)
Set #Date = GETDATE()
set #SearchDate = CAST(#Date as nvarchar(50))
set #SearchDate = REPLACE(#SearchDate,'-','')
CREATE TABLE TextData([SEMO_Data] [nvarchar](max) NULL)
Select #url = 'http://semorep.sem-o.com/DataCollection/DataSets.asmx/queryDatasetXML?DatasetName=SET_CAL&User=primplims#gmail.com&Password=testsemo&FromDate=20130103&ToDate=20130111&P1=Energy&P2=Statements&P3=Initial&P4=&P5='
EXEC #hr=sp_OACreate 'WinHttp.WinHttpRequest.5.1',#win OUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win, 'Open',NULL,'GET',#url,'false'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win,'Send'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
INSERT XMLParsing.dbo.TextData(SEMO_Data)
EXEC #hr=sp_OAGetProperty #win,'ResponseText'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OADestroy #win
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
This is a follow on from my last question. Am hoping that it will be seen easier if I post a new question.
I know it's too late, 2022, but i had the same problem today, this solved for me:
https://stackoverflow.com/a/38918970/1750527
Spoiler: queries run outside SSMS has a default text size of 2048. I needed to add a
SET TEXTSIZE 2147483647;
before my script so it run properly.
This is my first attempt at writing a stored procedure that emails someone. When trying to execute I get these errors:
Msg 102, Level 15, State 1, Procedure EmailTodaysErrors, Line 14
Incorrect syntax near '#MailServer'.
Msg 137, Level 15, State 2, Procedure EmailTodaysErrors, Line 26
Must declare the scalar variable "#mailserver".
Msg 137, Level 15, State 2, Procedure EmailTodaysErrors, Line 33
Must declare the scalar variable "#Body".
The code that I am using which is causing this is:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE EmailTodaysErrors
#SenderName varchar(100),
#SenderAddress varchar(100),
#RecipientName varchar(100),
#RecipientAddress varchar(100),
#Subject varchar(200),
#Body varchar(8000)
#MailServer varchar(100) = 'localhost'
AS
SET NOCOUNT ON;
declare #oMail int --Object reference
declare #resultcode int
EXEC #resultcode = sp_OACreate 'CDONTS.NewMail', #oMail OUT
if #resultcode = 0
BEGIN
EXEC #resultcode = sp_OASetProperty #oMail, 'RemoteHost', #mailserver
EXEC #resultcode = sp_OASetProperty #oMail, 'FromName', #SenderName
EXEC #resultcode = sp_OASetProperty #oMail, 'FromAddress', #SenderAddress
EXEC #resultcode = sp_OASetProperty #oMail, 'From', #SenderAddress
EXEC #resultcode = sp_OASetProperty #oMail, 'To', #RecipientAddress
EXEC #resultcode = sp_OASetProperty #oMail, 'Subject', #Subject
EXEC #resultcode = sp_OASetProperty #oMail, 'Body', #Body
EXEC #resultcode = sp_OAMethod #oMail, 'Send', NULL
EXEC sp_OADestroy #oMail
END
set nocount off
GO
You're missing a comma after the #body line, which is throwing off your declarations.
Add it here:
#Body varchar(8000), -- HERE
#MailServer varchar(100) = 'localhost'
Don't use sp_oa_family to send mail, there is already a built-in solution with SQL Server: Database Mail. Simply configure Database Mail properly on your server, then call sp_send_dbmail.
There's a comma missing in your parameters :
#Body varchar(8000), ---- HERE
#MailServer varchar(100) = 'localhost'
From my blog post, Create a Database Mail Configuration Using T-SQL Script, published 05 Feb 2018:
--Sending Test Mail
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'TestProfile',
#recipients = 'To Email Here',
#copy_recipients ='CC Email Here', --For CC Email if exists
#blind_copy_recipients= 'BCC Email Here', --For BCC Email if exists
#subject = 'Mail Subject Here',
#body = 'Mail Body Here',
#body_format='HTML',
#importance ='HIGH',
#file_attachments='C:\Test.pdf'; --For Attachments if exists
Can I call a remote webservice from a Stored Procedure and use the values that areretuned?
If you're using SQL 2005/2008, you could do this from a CLR stored procedure if you have the ability to install and run these. For more info:
http://msdn.microsoft.com/en-us/library/ms190790.aspx
Service Broker might provide the sort of functionality you're looking for here.
As The AntiSanta says, using a CLR stored procedure this is possible. The real question is whether you can avoid it altogether. It feels upside-down to call a web service from a stored procedure. Ideally you'd have some other service/app/layer that calls both the stored procedure and a web service. Possibly the stored proc returns parameter values for the web service, and you commit your local transaction after the WS call is complete.
This would make both debugging, deployment and support much more simple in the long run, and decouples the direct reference between the stored proc and the web service.
On SQL Server 2000 and up (if CLR is not enabled), you can use COM through stored procedures (sp_OACreate, sp_OAMethod, etc) if you have an existing COM wrapper for your web service.
Here is my code that works.
exec #hr = sp_OACreate 'MSXML2.ServerXMLHttp', #obj OUT
if #hr < 0 begin Raiserror('sp_OACreate MSXML2.ServerXMLHttp failed',16,1)
return end
exec #hr = sp_OAMethod #obj, 'Open', NULL, 'GET', #UrlString, false
if #hr <0 begin set #msg = 'sp_OAMethod Open failed' goto eh end
exec #hr = sp_OAMethod #obj, 'send'
if #hr <0 begin set #msg = 'sp_OAMethod Send failed' goto eh end
exec #hr = sp_OAGetProperty #obj, 'status', #status OUT
if #hr <0 begin set #msg = 'sp_OAMethod read status failed' goto eh end
if #status <> 200 begin set #msg = 'sp_OAMethod http status ' +str(#status) goto eh end
exec #hr = sp_OAGetProperty #obj, 'responseText', #response OUT
if #hr <0 begin set #msg = 'sp_OAMethod read response failed' goto eh end
exec #hr = sp_OADestroy #obj
select #response
......
eh:
exec #hr = sp_OADestroy #obj
Raiserror(#msg, 16, 1)
Return