Failed to initialize sqlcmd library with error number -2147467259 - sql-server

I am getting error of Failed to initialize sqlcmd library with error number -2147467259
while running below query, I tried with giving database name also but it is not working getting same error again and again. Can someone help me out in this regards.
declare #subject_line varchar (200)
declare #sql_query varchar (8000)
set #subject_line=(select 'Find Highest - ' + convert
(varchar(25),getdate(),120))
set #sql_query=(select 'select a.productname, a.groupid, c.productstatus,
releasedate from #tmpa a
join #tmpb b on a.productname = b.productname and a.prodgroupseqnr = b.maxpg
left join [Repository_PROD].[dbo].[Product_Info] c on a.productname =
c.product_EDP
order by 1')
EXEC msdb.dbo.sp_send_dbmail
#recipients=N'abc#gmail.com',
#subject= #subject_line,
#body= 'Hi ,
Please find attached output of given query .
Regards,
SQLDBA_TEAM
',
#execute_query_database = 'Repository_PROD',
#query_result_header = 1,
#query= #sql_query,
#profile_name ='SQLDBA',
#query_result_width=6000,
#query_result_separator =' ',
#query_no_truncate = 1,
#query_result_no_padding = 1,
#query_attachment_filename ='Find Highest.xls',
#attach_query_result_as_file = 1 ;

You can't use a temporary table when using database mail. You'll also need to include the database name in all tables that are being accessed, for example,
FROM ' + DB_NAME() + '.dbo.TableName makes it portable across databases.

I was also facing the same issue. Then I found the user who is calling the job is not added in SQL server logins folder of Security. I added that user in Security->Logins. It is working fine.

Related

Failed to initialize sqlcmd library with error number -2147024809

I created a new email profile with the super admin and I configured the smtp.
Then when I execute this query:
exec msdb.dbo.sp_send_dbmail
#profile_name ='admin_mail',
#recipients = 'firstname.lastname#email.com',
#execute_query_database = 'DashboardPowerBi',
#query = 'select top 20 from Client_1',
#subject= 'Liste des clients',
#body_format ='HTML',
#attach_query_result_as_file = 1;
I get this error:
Failed to initialize sqlcmd library with error number -2147024809
Recently i had an issue related with this, the solution here was to fully qualified the DATABASE + SCHEMA_NAME + TABLE_NAME ('select * from sales..sales_month'), even if you're in the same database.
Regards!
Well, the query is incorrect. You need to specify which columns you are selecting
#query = 'select top 20 * from Client_1',
But rather than using '*', actually list the columns you want.
I also had this error message. It ended up being I didn't have the database tables fully qualified in the query. database.schema.tablename I only had the tablename.
While searching, others had this error because the file attachment was too large.
You can change that in SSMS - Management - Database Mail
In my case, After I had tested the query and encapsulated in a string, I had forgotten to update...
'' AS Blank
to
'''' AS Blank
The Problem is with the directly passing query in #qry.
Try to insert the record to be attached in Global TempTable (##Temp) and try to use that select script with specified column names. Like Below
DECLARE #qry varchar(8000) = 'SET NOCOUNT ON
SELECT
Column1,
Column2
From ##TEMPEMAIL
SET NOCOUNT OFF'
I found that you could not have brackets around your FQDN, so change this
SET #sql = 'SELECT field1, field2, etc FROM [DBNAME].[dbo].[Table1]'
to this instead.
SET #sql = 'SELECT field1, field2, etc FROM DBNAME.dbo.Table1'

Dynamic bulk insert silently failing

I have a job that runs nightly to load a bunch of flat files to a database (around 250 files/tables, runs for around one hour). It uses a cursor to loop through the tables, and runs the following dynamic query to build and execute a bulk insert of the data.
select #sql = 'BULK INSERT tmp.VW_' + #tableName
+ ' FROM ''' + #filePath + #fileName
+ ''' WITH(FIELDTERMINATOR = '''
+ #fieldTerminator + ''',ROWTERMINATOR = '''
+ #rowTerminator + ''', KEEPNULLS,TABLOCK);'
exec (#sql)
Three times in the past year this statement has silently failed for the entire job. What I mean by this is the cursor loops through each table, it logs that the data is loaded for all tables, but when I check the data all 250 tables are empty.
When I re-run the job it works fine and all the data is loaded. When there are issues with the file format, SQL deadlock, TCP connection issues the job stops loading and logs the error.
I have checked the server logs and see nothing, and nothing in my jobs logs either. I've tried recreating the issue, but without success. As I mentioned it has happened 3x in the past year, but 0x in the previous three years this job has run.
Any idea what is happening or how to prevent it?
Can you wrap everything in a Try...Catch?
BEGIN TRY
select #sql = 'BULK INSERT tmp.VW_' + #tableName
+ ' FROM ''' + #filePath + #fileName
+ ''' WITH(FIELDTERMINATOR = '''
+ #fieldTerminator + ''',ROWTERMINATOR = '''
+ #rowTerminator + ''', KEEPNULLS,TABLOCK);'
exec (#sql)
END TRY
GO
-- The previous GO breaks the script into two batches,
-- generating syntax errors. The script runs if this GO
-- is removed.
BEGIN CATCH
-- Store exception information casting error message to varchar
SELECT #IsError = 1, #ErrorMessage = 'Exception message: ' + Cast (Error_Message() as varchar) + ';'
END CATCH
IF #IsError <> 0
BEGIN
DECLARE #Subject VARCHAR(250)
SELECT #Subject = 'Server Name: ' + ##SERVERNAME + '; Database Name: ' + DB_NAME() + ';' + ' - Email failed'
EXEC msdb.dbo.sp_send_dbmail #recipients = 'AlertSupport#abc.com'
, #from_Address = 'sqlemail.abc.com'
, #body = #ErrorMessage
, #subject = #Subject
, #profile_name = 'DBProfileName'
Raiserror('Error encountered while sending email', 16, 1);
END
GO
I experienced some weirdness a few years back doing something similar. We never figured out what the issue was, but it seemed like something was taking down SQL my Server overnight. Eventually I created a VB.NET .exe that fired off every few minutes, using Windows Task Scheduler, and the .exe checked to see if SQL Server was running or not. If the .exe found SQL Server was not running, it started it up. We never figured out what was taking it down...

T-SQL inconsistent sp_send_dbmail results

I have a job set up on a handful of servers (all in the same domain). The job sends an email via sp_send_dbmail, and the subject of the email should look like the following format:
=servername (ip address)= Weekly DB Backup to Azure Report
So as a potential example (obviously replace the 0s with actual IP address of the server SQL is running on):
=SQLMACHINE (000.000.000.00)= Weekly Backup to Azure Report
DBmail is configured, and I created the backup job. The T-SQL job step that sends the email has the following script:
SET NOCOUNT ON
DECLARE #ipAddress NVARCHAR(100)
SELECT #ipAddress = local_net_address
FROM sys.dm_exec_connections
WHERE Session_id = ##SPID;
DECLARE #subjectText NVARCHAR(255) = N'=' +
CAST(LEFT(##SERVERNAME, CHARINDEX('\', ##SERVERNAME)-1) AS NVARCHAR) + N'.' +
CAST(DEFAULT_DOMAIN() AS NVARCHAR) + N' ('+ #ipAddress +
N')= Weekly DB Backup to Azure Report'
DECLARE #tableHTML NVARCHAR(MAX) = N'this part works fine'
exec msdb.dbo.sp_send_dbmail #profile_name = 'Production Mail',
#recipients = 'xxx#xxx.com',
#subject = #subjectText,
#body = #tableHTML,
#body_format = 'HTML'
Each of the 5 servers has the same exact job definition - I have 1 source-controlled definition of the job that I use to create the job on each server.
Each week when the jobs run, most of them kick off an email with the expected subject line. Every couple weeks though, an email comes through with the subject SQL Server Message, which is what happens when no subject has been specified. Each time this happens, it could be on any one of the five servers. I'm not sure what's happening, since it should have a subject each time it executes.
EDIT:
This is happening because the #ipAddress variable is null. No idea why
SELECT #ipAddress = local_net_address
FROM sys.dm_exec_connections
WHERE Session_id = ##SPID;
would return null though...
local_net_address will be always NULL if a connection is not using the TCP transport provider. It's likely you use 'Shared memory' in net_transport.
You can force to use TCP when you create a connection, so local_net_address will be populated. E.g. when you open SSMS, you can specify the server name as "tcp:ServerName\InstanceName"
Below also can be used to retrieve the server properties (using TCP transport):
SELECT
CONNECTIONPROPERTY('net_transport') AS net_transport,
CONNECTIONPROPERTY('protocol_type') AS protocol_type,
CONNECTIONPROPERTY('auth_scheme') AS auth_scheme,
CONNECTIONPROPERTY('local_net_address') AS local_net_address,
CONNECTIONPROPERTY('local_tcp_port') AS local_tcp_port,
CONNECTIONPROPERTY('client_net_address') AS client_net_address
Your #ipAddress value could be null
Replace this code:
+ #ipAddress +
with this code
+ ISNULL(#ipAddress,'0.0.0.0') +
to prove that is the issue.

Find who/when a SQL view is dropped in SQL Server

In one of our SQL Server databases we have many SQL views. One particular view keeps disappearing every few weeks, and I want to find out what is happening.
Is there a way to query SQL Server to find out when and who dropped the view?
Alternatively, is it possible to add a SQL Server trigger on the DROP view command to capture and fail the DROP?
This information is written to the default trace. Below is an example query to glean the information.
SELECT
te.name
,tt.DatabaseName
,tt.StartTime
,tt.HostName
,tt.LoginName
,tt.ApplicationName
,tt.LoginName
FROM sys.traces AS t
CROSS APPLY fn_trace_gettable(
--get trace folder and add base file name log.trc
REVERSE(SUBSTRING(REVERSE(t.path), CHARINDEX(N'\', REVERSE(t.path)), 128)) + 'log.trc', default) AS tt
JOIN sys.trace_events AS te ON
te.trace_event_id = tt.EventClass
JOIN sys.trace_subclass_values AS tesv ON
tesv.trace_event_id = tt.EventClass
AND tesv.subclass_value = tt.EventSubClass
WHERE
t.is_default = 1 --default trace
AND tt.ObjectName = N'YourView'
AND tt.DatabaseName = N'YourDatabase';
Note the default trace is a rollover trace that keeps a maximum of 100MB so it might not have the forensic info if the view was recreated a while ago.
Yes, this is a DDL trigger. Sample trigger text is included in MSDN article about this kind of triggers. I'd say such a trigger is a must on production database for auditing reasons.
https://technet.microsoft.com/en-us/library/ms187909.aspx
Another trick is to create dependent on this object (view) another object (view?) with SCHEMA_BINDING option. This will make impossible to drop any object schema-bound object depends on.
To expand on another answer, here is some code to get started with a DDL trigger for DROP_VIEW. As an example, let's suppose someone dropped the view [HumanResources].[vEmployee] from the AdventureWorks database. The EVENTDATA() will look something like this:
<EVENT_INSTANCE>
<EventType>DROP_VIEW</EventType>
<PostTime>2016-02-26T09:02:58.190</PostTime>
<SPID>60</SPID>
<ServerName>YourSqlHost\SQLEXPRESS</ServerName>
<LoginName>YourDomain\SomeLogin</LoginName>
<UserName>dbo</UserName>
<DatabaseName>AdventureWorks2012</DatabaseName>
<SchemaName>HumanResources</SchemaName>
<ObjectName>vEmployee</ObjectName>
<ObjectType>VIEW</ObjectType>
<TSQLCommand>
<SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" />
<CommandText>DROP VIEW [HumanResources].[vEmployee]
</CommandText>
</TSQLCommand>
</EVENT_INSTANCE>
And here is a possible DDL trigger statement:
CREATE TRIGGER trgDropView
ON DATABASE
FOR DROP_VIEW
AS
BEGIN
--Grab some pertinent items from EVENTDATA()
DECLARE #LoginName NVARCHAR(MAX) = EVENTDATA().value('(/EVENT_INSTANCE/LoginName)[1]', 'NVARCHAR(MAX)')
DECLARE #TsqlCmd NVARCHAR(MAX) = EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)')
--Now do something. Lots of possibilities. Here are two:
--1) Send Email
DECLARE #Subj NVARCHAR(255) = ##SERVERNAME + ' - VIEW DROPPED'
DECLARE #MsgBody NVARCHAR(255) = 'Login Name: ' + #LoginName + CHAR(13) + CHAR(10) +
'Command: ' + #TsqlCmd
EXEC msdb..sp_send_dbmail
#recipients = 'You#YourDomain.com',
#subject = #Subj,
#body = #MsgBody
--2) Log an error
DECLARE #ErrMsg NVARCHAR(MAX) = ##SERVERNAME + ' - VIEW DROPPED' + CHAR(13) + CHAR(10) +
'Login Name: ' + #LoginName + CHAR(13) + CHAR(10) +
'Command: ' + #TsqlCmd
RAISERROR(#ErrMsg, 16, 1) WITH LOG;
END
You can also create a trigger at the server level in order to capture and log DDL changes on the database :
CREATE TRIGGER [Trg_AuditStoredProcedures_Data]
ON ALL SERVER
FOR CREATE_PROCEDURE,ALTER_PROCEDURE,DROP_PROCEDURE,CREATE_TABLE,ALTER_TABLE,
DROP_TABLE,CREATE_FUNCTION,ALTER_FUNCTION,DROP_FUNCTION,CREATE_VIEW,ALTER_VI EW,
DROP_VIEW,CREATE_DATABASE,DROP_DATABASE,ALTER_DATABASE,
CREATE_TRIGGER,DROP_TRIGGER,ALTER_TRIGGER
AS
SET ANSI_PADDING ON
DECLARE #eventdata XML;
SET #eventdata = EVENTDATA();
SET NOCOUNT ON
/*Create table AuditDatabaseObject in order to have a history tracking for every DDL change on the database*/
INSERT INTO AuditDatabaseObject
(DatabaseName,ObjectName,LoginName,ChangeDate,EventType,EventDataXml,HostName)
VALUES (
#eventdata.value('(/EVENT_INSTANCE/DatabaseName)[1]','sysname')
, #eventdata.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname')
, #eventdata.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname')
, GETDATE()
, #eventdata.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname')
, #eventdata
, HOST_NAME()
);
DECLARE #Valor VARCHAR(30),#EvenType VARCHAR(30)
SET #Valor = #eventdata.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname')
SET #EvenType = #eventdata.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname')
IF (IS_SRVROLEMEMBER('sysadmin',#Valor) != 1 AND #EvenType = 'DROP_DATABASE')
BEGIN
ROLLBACK
END
you can find more information here EVENTDATA()
if an object is dropped from the database you will see a record created on the table AuditDatabaseObject
also keep in mind security as # Chris Pickford mentioned.

Generic failure using sp_send_dbmail in SQL Server 2014

I'm trying to use sp_send_dbmail to send the results of a query through a SQLAgent job in SQL Server 2014. I believe I have my DBMail profile set up properly but when running this:
exec msdb.dbo.sp_send_dbmail
#profile = 'TestProfile',
#recipients = 'testmail#gmail.com',
#subject = 'Test',
#query = 'SELECT id FROM TestTable',
#attach_query_result_as_file = 1,
#query_attachment_filename = 'TestValues.txt'
I get the following error message:
Failed to initialize sqlcmd library with error number -2147467259.
Googling this error message didn't turn up anything useful, likely due to the generic error number. Anyone have some insight into this error message?
I found that despite both my query window (for testing) and SqlAgent job were pointing at my desired DB, sp_send_dbmail doesn't seem to have any database context. My original post was failing because SQL didn't know where to run SELECT * FROM TestTable. The fix is to provide sp_send_dbmail with database context by either fully qualifying your table in the #query parameter:
#query = 'SELECT id FROM testDB.dbo.TestTable'
or by providing the optional #execute_query_database parameter:
#execute_query_database = 'testDB'
Enable sysadmin server role for the account that is used to run the SQL Server Agent.Below are the screenshots.
Error
Fix
Now the SQL Server Job runs without any errors and I get an email from dbmail.
There's another reason why you might get this error; if the query has an issue.
In our case we had (note that it's not due to a syntax error; note the missing quotes):
DECLARE #EmailQuery varchar(max) = 'select
e.Field1,
REPLACE(REPLACE(e.ExceptionReason, CHAR(13), ''), CHAR(10), '') ExceptionReason,
e.UserName
from dbo.tblException e'
Once we corrected it as follows, it worked fine:
DECLARE #EmailQuery varchar(max) = 'select
e.Field1,
REPLACE(REPLACE(e.ExceptionReason, CHAR(13), ''''), CHAR(10), '''') ExceptionReason,
e.UserName
from dbo.tblException e'

Resources