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'
Related
Platform: SQL Server 2016
I've written a SQL statement that outputs a series of SQL commands and I want to execute the output of this query in the same script. This is the query that builds the commands I want to execute.
select
'ALTER SCHEMA dbo TRANSFER SYSNET.' + name + ';'
from
sys.tables
where
schema_name(schema_id) = 'sysnet'
order by
1;
I know I need to capture the output in a variable and then execute it. I'm sure it's simple but everything I've tried didn't work and Google has failed me.
==================================================
Thanks for the answers! scsimon technically gave the best answer since it provided the means of executing the output of any dynamic SQL and that's what I asked for. With that said, Ross Bush provided the simplest way for me to accomplish this specific task of transferring schema ownerships. In the end I used this...
EXEC sp_MSforeachtable #command1='ALTER SCHEMA dbo TRANSFER ?;'
,#whereand='AND schema_name(schema_id) = ''sysnet'''
Just loop through those seems to be what you want.
select row_number() over (order by (select null)) as RN, 'ALTER SCHEMA dbo TRANSFER SYSNET.'+ name + ';' as CMD
into #mytemp
from sys.tables where
schema_name(schema_id) = 'sysnet'
declare #sql varchar(max)
declare #i int = 1
while #i <= (select max(RN) from #mytemp)
begin
select #sql = CMD from #mytemp where RN = #i
print #sql
--exec(#sql)
set #i = #i + 1
end
drop table #mytemp
This is not the best advice as the function below is an undocumented SQL Server function and may not be around in the future. That being said, I would use the sp_MSforeachtable table to issue a command for each table in the target database.
EXEC sp_MSforeachtable 'SELECT COUNT(*) FROM ?'
sorry I am uploading a pic of my query as I dont know to format my text...as a newbie its confusing.
So you want to execute:
select * from File_20170703 -- where your table name is a variable.
It is not possible to use variables for table or column names, what you need to do is to build a dynamic sql and execute it using sp_executesql.
here is an example:
DECLARE #sql nvarchar(4000)
SELECT #sql = 'SELECT * FROM File_20170703'
EXEC sp_executesql #sql
More info about dynamic sql
A simple TSQL "dynamic sql" looks like this:
DECLARE #file_name AS VARCHAR(100)
DECLARE #query AS VARCHAR(MAX)
SET #file_name = 'file_20170101'
SET #query = 'SELECT * FROM ' + #file_name
execute(#query)
Basically you need to create a valid sql query by concatenating various parts of the query together, then you can execute that whole big string as your query.
You can use SQL Cursor along with while loop. Examples are given here:
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql
I need to TRIM databases as per requirement. So, I'm using below script and giving database names manually. All I need is to automate the script to get database names automatically. Can anyone please suggest how to get the database name automatically.
Use [Sales_backup_2015_05_31_230001_7137975]
Exec [spMaint_TrimTestDB] 1
Go
for Eg:
instead of giving manually Sales_backup_2015_05_31_230001_7137975 I need to get db name automatically
Thanks.
There is a function DB_NAME() that would return the name of the current database if no parameters are passed. Check this.
I guess dynamic SQL might help you to run SP in different databases:
DECLARE #sql nvarchar(max)
SELECT #sql = (
SELECT N'Use '+QUOTENAME([name]) +' Exec [spMaint_TrimTestDB] 1;'
FROM sys.databases
WHERE database_id >= 5 AND [name] like 'Sales_backup%'
FOR XML PATH('')
)
EXEC sp_executesql #sql
This script will create and execute dynamic statement like:
Use [sales_backup_2015] Exec [spMaint_TrimTestDB] 1;
Use [sales_backup_2016] Exec [spMaint_TrimTestDB] 1;
etc...
I am doing work for a company that stores each of their client's info in a different database. When a table needs modification, I have to go to each database and run the ALTER TABLE script. Is there a way I can use a prepared statement to run through all 100+ DBO names?
ALTER TABLE ?.dbo.profileTable
ADD COLUMN profileStatus int
where ? = 'CompanyA, CompanyB, CompanyC' or something similar?
Use Sp_MSforeachdb
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; alter query'
[?] is used as a placeholder for the heretofore unspecified database name
You can modify the query as per your needs ,to exclude system databases use like below..
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; IF DB_ID(''?'') > 4 begin yourquery end'
This will exclude any database that does not have the table you are looking for including system databases.
Declare #TableName Varchar(8000) = 'ProfileTable'
Declare #Sql Varchar(8000)
Select #Sql = Stuff(
(Select ';', 'Alter Table ' + Name + SqlText
From sys.databases
Cross Apply (Select '.dbo.profileTable ADD profileStatus int' SqlText) CA
Where Case When State_Desc = 'ONLINE'
Then Object_Id (QuoteName(Name) + '.[dbo].' + #TableName, 'U')
End Is Not Null
FOR XML PATH('')
),1,1,'')
Exec (#Sql)
This ? before is database ([database].[schema].[table]). Thus you can use sp_MSforeachdb or, as I prefer, use sys.databases view to prepare dynamic queries.
Beware, both methods can interfere with system databases.
Take a look at this solution:
DECLARE #query nvarchar(MAX)='';
SELECT #query = #query + 'USE '+QUOTENAME(name)+';ALTER TABLE dbo.profileTable ADD profileStatus int;'
FROM sys.databases
WHERE OBJECT_ID(QUOTENAME(name)+'.dbo.profileTable', 'U') IS NOT NULL
EXEC(#query)
It adds column col1 int to each dbo.profileTable in every database.
Is it natural that SQL Server does not catch objects dependencies in stored procedures through dynamic SQL:
CREATE PROCEDURE testSp (#filter nvarchar(max)) AS
exec ('select * from testTable where 1=1 AND '+ #filter)
Here SQL Server will not detect dependency between testTable and testSp.
What kind of "advice" do you have for the DBMS? I propose it could be very "cheap query" :
CREATE PROCEDURE testSp (#filter nvarchar(max)) AS
-- cheap query like 'select top 1 #id=id from testTable'
exec ('select * from testTable where 1=1 AND '+ #filter)
So the question is which queries could be good candidates for that purpose?
P.S. Of course I expect that they all will have their minuses..
When using dynamic SQL the query parts that are tekst (between quotes) are not detected as code by the IDE or the engine until the moment they are excuted. So this answers your first question, yes it is natural.
The only way around this that I can think of is to create a view using the generated output of the dynamic sql and check if the view definition is still valid at any point you want to check if the procedure is valid.
Usually when you need to do something like this there is an earlier departure from standard methods that if handled removes the need for such silly tricks.
Example:
USE demo
GO
DECLARE #sql NVARCHAR(MAX) = '
SELECT firstname, lastname FROM dbo.employees'
DECLARE #view NVARCHAR(MAX) = '
CREATE VIEW dbo.test_view
AS ' + #sql
EXEC sp_executesql #view
BEGIN TRY
DECLARE #validation int = (SELECT TOP 1 COUNT(*) FROM demo..test_view)
EXEC sp_executesql #sql
END TRY
BEGIN CATCH
PRINT 'Dynamic SQL out of date'
END CATCH
SET NOEXEC ON
select * from testTable
SET NOEXEC OFF
do the job: code really not executed, but dependecy is declared.