i wrote a procedure in which i tried to send mail using below command.
EXEC Sp_send_cdontsmail 'from','to','Test','TEST DATA'
After executing its showing "Command(s) completed successfully."
but i am not getting any mail.please help me on this.
You need to configure Database Mail and then use sp_send_dbmail to send mail. This is a supported procedure, part of the SQL Server.
PS. I am aware that out there some code sample circulates that advocates something along the lines of:
CREATE PROCEDURE [dbo].[sp_send_cdontsmail]
...
EXEC #hr = master..sp_OACreate 'CDONTS.NewMail', #MailID OUT
EXEC #hr = master..sp_OASetProperty #MailID, 'From',#From
EXEC #hr = master..sp_OASetProperty #MailID, 'Body', #Body
...
This is horrible code. As one can easily see there is absolutely 0 (zero, nada, zip) error checking in this code. Any failure will be reported as 'success'. COM interop will not raise T-SQL notification messages, is all in the HRESULT, which goes unchecked. Steer away from such code.
Related
I need some out-of-the-box thinking on this issue. It's weird.
I have a SQL Server environment (production) where I get a sporadic error executing a procedure.
dbo.proc_1_$sp
...
begin try
BEGIN
SELECT #errmsg = 'failed to execute proc2_$sp'
EXEC proc2_$sp;
END;
...
catch
... etc
EXEC proc2_$sp fails.
It returns error
failed to execute proc2_$sp
to a process log table.
The problem is... I don't execute dbo.proc_1_$sp.
I want to find out what executes it. It could be a test environment pointing to production, it could be a test script someone left running.
I want to know the hostname, the login name, or whatever info I can catch on this process.
I can't leave SQL Server Profiler trace on. I tried, but it's a prod environment and I can't let the trace running for hours.
The only way I can think of is to update the error message with more info, as below.
The problem is, since I don't know the login name, I can't ensure the user will have access to sys.sysprocesses and I might get a crash instead.
Any other suggestions on how I can grab process information without worrying about permission issues?
dbo.proc_1_$sp
...
begin try
BEGIN
SELECT #errmsg = 'failed to execute proc2_$sp'
select #errmsg = #errmsg + ' login_time:'+convert(nvarchar, login_time, 9)+' hostname:'+ltrim(rtrim(hostname)) + ' program_name:'+ltrim(rtrim(program_name))+' loginame:'+loginame
FROM sys.sysprocesses WHERE spid = ##SPID
EXEC proc2_$sp;
END;
...
catch
... etc
In my SQL, I already created profile & account.
I also know how to send the message though code :
USE msdb
GO
EXEC sp_send_dbmail #profile_name='yourprofilename',
#recipients='test#Example.com',
#subject='Test message',
#body='This is the body of the test message.
Congrates Database Mail Received By you Successfully.'
** Above is an example
However, I was wondering how can I insert an image into the message.
I have two service programs: mySrvPgm and myErr
mySrvPgm has a procedure which contains:
/free
...
exec sql INSERT INTO TABLE VALUES(:RECORD_FMT);
if sqlError() = *ON;
//handle error
endif;
...
/end-free
myErr has a procedure sqlError:
/free
exec sql GET DIAGNOSTICS CONDITION 1
:state = RETURNED_SQLSTATE;
...
/end-free
Background info: I am using XMLSERVICE to call the given procedure in mySrvPgm from PHP. I am not using a persistent connection. myErr is bound-by-reference via a binding directory used by mySrvPgm. Its activation is set to *IMMED, its activation group is set to *CALLER.
The problem: Assume there is an error on the INSERT statement in mySvrPgm. The first time sqlError() is called it will return SQLSTATE 00000 despite the error. All subsequent calls to sqlError() return the expected SQLSTATE.
A workaround: I added a procedure to myErr called initSQL:
/free
exec sql SET SCHEMA MYLIB;
/end-free
If I call initSQL() before the INSERT statement in mySrvPgm, sqlError() functions correctly. It doesn't have to be SET SCHEMA, it can be another GET DIAGNOSTICS statement. However, if it does not contain an executable SQL statement it does not help.
The question: I believe the myErr service program is activating properly and has the correct scope, but I am wondering if there is something more I need to do to activate the SQL part of it. Is there some way to set it up so SQL auto-initializes when the service program is activated, or do I have to execute an unneeded SQL statement in order to get it started?
There is some more background information available here.
Thank you for reading.
What version an release of the OS? Are you upto date on PTFs?
Honestly, seems to me that it's possibly a bug. Or the manual(s) need clarification.. I'd open a PMR.
Essentially I have a job which runs in BIDS and as as a stand lone package and while it runs under the SQL Server Agent it doesn't complete properly (no error messages though).
The job steps are:
1) Delete all rows from table;
2) Use For each loop to fill up table from Excel spreasheets;
3) Clean up table.
I've tried this MS page (steps 1 & 2), didn't see any need to start changing from Server side security.
Also SQLServerCentral.com for this page, no resolution.
How can I get error logging or a fix?
Note I've reposted this from Server Fault as it's one of those questions that's not pure admin or programming.
I have logged in as the proxy account I'm running this under, and the job runs stand alone but complains that the Excel tables are empty?
Here's how I managed tracking "returned state" from an SSIS package called via a SQL Agent job. If we're lucky, some of this may apply to your system.
Job calls a stored procedure
Procedure builds a DTEXEC call (with a dozen or more parameters)
Procedure calls xp_cmdshell, with the call as a parameter (#Command)
SSIS package runs
"local" SSIS variable is initialized to 1
If an error is raised, SSIS "flow" passes to a step that sets that local variable to 0
In a final step, use Expressions to set SSIS property "ForceExecutionResult" to that local variable (1 = Success, 0 = Failure)
Full form of the SSIS call stores the returned value like so:
EXECUTE #ReturnValue = master.dbo.xp_cmdshell #Command
...and then it gets messy, as you can get a host of values returned from SSIS . I logged actions and activity in a DB table while going through the SSIS steps and consult that to try to work things out (which is where #Description below comes from). Here's the relevant code and comments:
-- Evaluate the DTEXEC return code
SET #Message = case
when #ReturnValue = 1 and #Description <> 'SSIS Package' then 'SSIS Package execution was stopped or interrupted before it completed'
when #ReturnValue in (0,1) then '' -- Package success or failure is logged within the package
when #ReturnValue = 3 then 'DTEXEC exit code 3, package interrupted'
when #ReturnValue in (4,5,6) then 'DTEXEC exit code ' + cast(#Returnvalue as varchar(10)) + ', package could not be run'
else 'DTEXEC exit code ' + isnull(cast(#Returnvalue as varchar(10)), '<NULL>') + ' is an unknown and unanticipated value'
end
-- Oddball case: if cmd.exe process is killed, return value is 1, but process will continue anyway
-- and could finish 100% succesfully... and #ReturnValue will equal 1. If you can figure out how,
-- write a check for this in here.
That last references the "what if, while SSIS is running, some admin joker kills the CMD session (from, say, taskmanager) because the process is running too long" situation. We've never had it happen--that I know of--but they were uber-paranoid when I was writing this so I had to look into it...
Why not use logging built into SSIS? We send our logs toa database table and then parse them out to another table in amore user friendly format and can see every step of everypackage that was run. And every error.
I did fix this eventually, thanks for the suggestions.
Basically I logged into Windows with the proxy user account I was running and started to see errors like:
"The For each file enumerator is empty"
I copied the project files across and started testing, it turned out that I'd still left a file path (N:/) in the properties of the For Each loop box, although I'd changed the connection properties. Easier once you've got error conditions to work with. I also had to recreate the variable mapping.
No wonder people just recreate the whole package.
Now fixed and working!
I am currently having problems calling a stored procedure async from within a insert-update-trigger. For this I m using the service broker.
--message type
CREATE MESSAGE TYPE [TheMessage] VALIDATION = NONE
--contract
CREATE CONTRACT [TheContract] ([TheMessage] SENT BY ANY);
--queue
CREATE QUEUE [TheQueue] WITH ACTIVATION
(STATUS = ON, MAX_QUEUE_READERS = 1,
PROCEDURE_NAME = TheStoreProcedure,
EXECUTE AS OWNER);
--service
CREATE SERVICE [TheService] ON QUEUE [TheQueue] ([TheContract]);
Within the trigger:
DECLARE #Handle UNIQUEIDENTIFIER;
BEGIN DIALOG CONVERSATION #Handle
FROM SERVICE [TheService]
TO SERVICE 'TheService'
ON CONTRACT [TheContract]
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION #Handle
MESSAGE TYPE [TheMessage](N'some data');
Within the stored procedure:
DECLARE #Handle UNIQUEIDENTIFIER;
DECLARE #MessageType SYSNAME;
RECEIVE TOP (1)
#Handle = conversation_handle,
#MessageType = message_type_name
FROM [TheQueue];
IF(#Handle IS NOT NULL)
BEGIN
-- some statements
END
This setup doesn't seem to work. The trigger does not throw any errors so I assume the message is queued. But the receive within the stored doesn't seem to work. None of my statements are being executed.
Check if the message isn't retained in sys.transmission_queue. Transmission_status column should explain why the message isn't delivered.
Check if the message is in the queue: SELECT ... FROM [TheQueue]. If the message is there and the procedure didn't activate check the queue's is_receive_enabled status in sys.service_queues. If the queue is disabled, you probably rolled back 5 receives in a row during testing and triggered the poison message mechanism.
If the queue is enabled, check the queue monitors status, see Understanding Queue Monitors.
If the message is neither in the queue nor in transmission queue, it must been consumed by the activated procedure. Verify your ERRORLOG for any error output. Disable activation, send a message again, then run the procedure manually from an SSMS query window see if you get any error message.
Mae sure your activated procedure does not fall into the traps of the EXECUTE AS context. See Why does feature … not work under activation? and Call a procedure in another database from an activated procedure
Ok, thanks for your answers, I fixed it.
The problem was that the service broker was disabled..
USE AdventureWorks
GO
ALTER DATABASE AdventureWorks SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE AdventureWorks SET ENABLE_BROKER
ALTER DATABASE AdventureWorks SET MULTI_USER
GO