SQL Server mail variable usage - sql

I want to use send mail utility on SQL Server where the recipients variable (#recipients) should take a formatted string as value. I want to show an example below:
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Mail Profile',
#recipients = Right('domain/user#company.com',
CHARINDEX('/',reverse('domain/user#company.com'))-1),
#body = 'TEST MESSAGE',
#subject = 'Automated Success Message'
But when I execute the above statement the error message appears: Incorrect syntax near the keyword Right

You can't pass an expression to am SP as a parameter. You have to pass a literal value or a variable. You'll need to declare a variable first, set it's value and then pass it as the parameter:
DECLARE #recipients nvarchar(255);
SET #recipients = RIGHT('domain/user#company.com', CHARINDEX('/', REVERSE('domain/user#company.com')) - 1);
EXEC msdb.dbo.sp_send_dbmail #profile_name = 'Mail Profile',
#recipients = #recipients,
#body = 'TEST MESSAGE',
#subject = 'Automated Success Message';

Related

How to send json query as attachment using sp_send_dbmail

Is it possible to export the data from a column into json and email?
Col is NVARCHAR(MAX) storing entire json string.
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Profile',
#recipients = 'a#b.com',
#subject = #Subject,
#body = #Body,
#query = 'SELECT TOP(1) [col] FROM [dbo].[tbl] ORDER BY [Date] DESC;',
#execute_query_database = 'DBName',
#attach_query_result_as_file = 1,
#query_attachment_filename = 'Report.json';
Executing produces error:
Failed to initialize sqlcmd library with error number -2147417850.
Yes, that's possible. Seems like you're missing the required permissions (Executing sp_send_dbmail with an Agent Job: Failed to initialize sqlcmd library). And the #recipients parameter.

How to send http request in SSMS with Basic Authentication passing Username and Password?

So I'm using an API today that returns XML file upon http request. Today I don't have any authentication in this process, but API website will put more security in place. So instead of 'No Auth' I would need to be passing Username and Password.
Here's the code I'm using today
DECLARE #authHeader VARCHAR(64);
DECLARE #contentType VARCHAR(64);
DECLARE #responseText varchar(4000);
DECLARE #ret INT;
DECLARE #status VARCHAR(32);
DECLARE #statusText VARCHAR(32);
DECLARE #token INT;
DECLARE #url varchar(8000);
--DECLARE #username varchar(255); will use in the future
--DECLARE #password varchar(255); will use in the future
SET #authHeader = 'No Auth'
SET #contentType = 'application/xml';
SET #url = 'https://www.someurl.com/get_xml';
-- Open the connection.
EXEC #ret = sp_OACreate 'MSXML2.ServerXMLHTTP', #token OUT;
IF #ret <> 0 RAISERROR('Unable to open HTTP connection.', 10, 1);
-- Send the request.
EXEC #ret = sp_OAMethod #token, 'open', NULL, 'GET', #url, 'false'
EXEC #ret = sp_OAMethod #token, 'setRequestHeader', NULL, 'Authorization', #authHeader
EXEC #ret = sp_OAMethod #token, 'setRequestHeader', NULL, 'Content-type', #contentType;
EXEC #ret = sp_OAMethod #token, 'send'
-- Handle the response.
EXEC #ret = sp_OAGetProperty #token, 'status', #status OUT;
EXEC #ret = sp_OAGetProperty #token, 'statusText', #statusText OUT;
EXEC #ret = sp_OAGetProperty #token, 'responseText', #responseText OUT;
-- Show the response.
PRINT 'Status: ' + #status + ' (' + #statusText + ')';
PRINT 'response text: ' + #responseText;
-- Close the connection.
EXEC #ret = sp_OADestroy #token;
IF #ret <> 0 RAISERROR('Unable to close HTTP connection.', 10, 1);
How do I pass same http get request but with Basic Authentication, passing Username: Login and Password: Admin?
I've tried to research online but couldn't find much information in that regard

Run R-Script to get data from GoogleSheets on SQL Server

This code works fine on Visual Studio
OutputDataSet <- read.csv(file = "https://docs.google.com/spreadsheets/d/128qCX1YtvsHr4hERruFx6Ykn72qRkpRGH5brFULl7SY/pub?gid=0&single=true&output=csv", header = TRUE, sep = ",", encoding = "UTF-8", stringsAsFactors = FALSE)
OutputDataSet
I try to send this query using T-SQL
DECLARE #GoogleSheetURL nvarchar(500) =
'OutputDataSet <- read.csv(file = "https://docs.google.com/spreadsheets/d/128qCX1YtvsHr4hERruFx6Ykn72qRkpRGH5brFULl7SY/pub?gid=0&single=true&output=csv", header = TRUE, sep = ",", encoding = "UTF-8", stringsAsFactors = FALSE)'
EXEC sp_execute_external_script
#language =N'R',
#script = #GoogleSheetURL,
#input_data_1 = N' ;'
WITH RESULT SETS (([Дата] date,[Отдел] nvarchar(20),[Продукт] nvarchar(20),[Продавец] nvarchar(20),[Выставлено_шт] int,[Оплачено_шт] int,[Выставлено] int,[Оплачено] int ));
go
How it is possible to get data into SQL Server from GoogleSheet?
ErrorScreen
VSScreen
Here is answer..
There were two rules in windows firewall
AnswerScreen

sqlcmd not working inside inno setup even with result code equals zero

After googling a bunch and struggling for a day with no result, here I am.
I'm developing an installer using Inno Setup, which installs and properly configures MS SQL Server 2008 R2 according some user input from a wizard page containing checkboxes.
I have a procedure to do that SQL Server configuration setted like this:
Source: ".\src\{#ExecName}"; DestDir: "{app}"; Flags: ignoreversion; AfterInstall: runSQLCMD
where #ExecName is my .exe name;
here is the procedure:
[Code]
procedure runSQLCMD();
var
ResultCode: Integer;
SQLCMDPath: String;
SQLParams: String;
BasicQuery: String;
FullQuery: String;
begin
SQLCMDPath := ExpandConstant('{pf}') + '\Microsoft SQL Server\100\Tools\Binn\sqlcmd.exe'
BasicQuery := 'EXEC sp_configure ''show advanced option'', 1; RECONFIGURE; EXEC sp_configure ''max worker threads'', 256; RECONFIGURE; EXEC sp_configure ''backup compression default'', 1; RECONFIGURE; EXEC sp_configure ''max degree of parallelism'', 4; RECONFIGURE; EXEC sp_configure ''max server memory'', 512; RECONFIGURE;';
FullQuery := 'EXEC sp_configure ''show advanced option'', 1; RECONFIGURE; EXEC sp_configure ''backup compression default'', 1; RECONFIGURE; EXEC sp_configure ''max degree of parallelism'', 4; RECONFIGURE; EXEC sp_configure ''max server memory'', 1024; RECONFIGURE;';
if not FileExists(SQLCMDPath) then begin
SQLCMDPath := ExpandConstant('{pf64}') + '\Microsoft SQL Server\100\Tools\Binn\sqlcmd.exe'
end;
if (ShouldRunItem(1)) then begin
SQLParams := '-S .\INSTANCE -U sa -P "password" -Q "' + BasicQuery + '-o ' + ExpandConstant('{tmp}') + '\logsql.txt';
if (Exec(SQLCMDPath, SQLParams, '',SW_SHOW,ewWaitUntilIdle, ResultCode)) then begin
MsgBox('Success!', mbInformation, MB_OK);
end
else begin
MsgBox('Error', mbError, MB_OK);
end;
end;
if (ShouldRunItem(2)) then begin
SQLParams := '-S .\INSTANCE -U sa -P "password" -Q "' + FullQuery + '-o ' + ExpandConstant('{tmp}') + '\logsql.txt';
if (Exec(SQLCMDPath, SQLParams, '',SW_SHOW,ewWaitUntilIdle, ResultCode)) then begin
MsgBox('Success!', mbInformation, MB_OK);
end
else begin
MsgBox('Error', mbError, MB_OK);
end;
end;
end;
When the Exec statement runs, the ResultCode variable returns zero on debug, but when I right-click on server, point to Properties/Memory (on SSMS), the Memory configuration is not set with the user-chosen value. Not even the logsql.txt file is generated (I've opened the directory pointed by {tmp} constant and no .txt files there)
Running sqlcmd from cmd, using the same parameters and query, everything goes fine.
What I'm doing wrong?
Thank you in advance.
In my case it was not running because I had added "" around the SQLCMDPath variable. Once I removed them the -Q was executed successfully. Also, I used {commonpf} instead of {pf} as such := ExpandConstant('{commonpf}\Microsoft SQL Server\100\Tools\Binn\sqlcmd.exe');
Full code
procedure CurStepChanged(CurStep: TSetupStep);
var
sqlCmd: String;
dbCreate: String;
path: String;
ResultCode: Integer;
begin
path := ExpandConstant('{app}');
sqlCmd := ExpandConstant('{commonpf}\Microsoft SQL Server\100\Tools\Binn\sqlcmd.exe');
dbCreate := ' -S .\IVA -U sa -P sql -Q "CREATE DATABASE pos ON PRIMARY (NAME = N''pos'', FILENAME = N''' + path + '\pos.mdf'', SIZE = 73728KB, MAXSIZE = UNLIMITED ,FILEGROWTH = 65536KB) LOG ON (NAME = N''pos_log'', FILENAME = N''' + path + '\pos_log.ldf'', SIZE = 73728KB, MAXSIZE = 2048GB,FILEGROWTH = 65536KB)" -o "' + ExpandConstant('{app}\install.log') + '"';
// CurStep values
// ssInstall, ssPostInstall, ssDone
if CurStep = ssPostInstall then begin
// use log to view and test the string in a command window
Log('The Value is dbCreate: ' + dbCreate );
//MsgBox(sqlCmd + dbCreate, mbConfirmation, MB_YESNO)
if Exec(sqlCmd, dbCreate, '' , SW_HIDE, ewWaitUntilIdle, ResultCode) then
begin
MsgBox( 'Database is ready for use' , mbInformation, mb_Ok);
end
else begin
MsgBox(SysErrorMessage(ResultCode) , mbInformation, mb_Ok);
end;
end;
end;

How to use Inno Setup to update a database using .sql script

I'd like to compile a setup that will connect to a remote database using the credentials provided by the user, then install few db components using .sql script.
Is that possible using Inno Setup?
More details:
I'd like to have a custom form, asking the user to enter the database address and credentials, then run a command that will execute an sql script that will update the remote database server.
If the update is successful - complete the installation with success.
This is rather general question - I have a lot of customized setups that should connect to different servers/run different scripts - the idea is to build a generic form that will provide this functionality.
I don't think you can have a completely generic form, as for different servers you may need either a single connection string, or a server name and an (optional) port; for some servers you will use system authentication, for others a user name password tuple.
Having said that I will give you a small demo Inno script that asks for server name and port, user name and password, then makes a few tests, then executes an application that is extracted (by code) to the temp directory and will be deleted by the installer. You can use this as a starting point for your scripts. Having a few of such snippets, and including them in your scripts as necessary will probably be all you need:
[Setup]
AppID=DBUpdateTest
AppName=Test
AppVerName=Test 0.1
AppPublisher=My Company, Inc.
DefaultDirName={pf}\Test
DefaultGroupName=Test
DisableDirPage=yes
DisableProgramGroupPage=yes
OutputBaseFilename=setup
PrivilegesRequired=none
[Files]
Source: "isql.exe"; DestDir: "{tmp}"; Flags: dontcopy
Source: "update_V42.sql"; DestDir: "{tmp}"; Flags: dontcopy
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Code]
var
DBPage: TInputQueryWizardPage;
procedure InitializeWizard;
begin
DBPage := CreateInputQueryPage(wpReady,
'Database Connection Information', 'Which database is to be updated?',
'Please specify the server and the connection credentials, then click Next.');
DBPage.Add('Server:', False);
DBPage.Add('Port:', False);
DBPage.Add('User name:', False);
DBPage.Add('Password:', True);
DBPage.Values[0] := GetPreviousData('Server', '');
DBPage.Values[1] := GetPreviousData('Port', '');
DBPage.Values[2] := GetPreviousData('UserName', '');
DBPage.Values[3] := GetPreviousData('Password', '');
end;
procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
SetPreviousData(PreviousDataKey, 'Server', DBPage.Values[0]);
SetPreviousData(PreviousDataKey, 'Port', DBPage.Values[1]);
SetPreviousData(PreviousDataKey, 'UserName', DBPage.Values[2]);
SetPreviousData(PreviousDataKey, 'Password', DBPage.Values[3]);
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
ResultCode: Integer;
begin
Result := True;
if CurPageID = DBPage.ID then begin
if DBPage.Values[0] = '' then begin
MsgBox('You must enter the server name or address.', mbError, MB_OK);
Result := False;
end else if DBPage.Values[2] = '' then begin
MsgBox('You must enter the user name.', mbError, MB_OK);
Result := False;
end else if DBPage.Values[3] = '' then begin
MsgBox('You must enter the user password.', mbError, MB_OK);
Result := False;
end else begin
ExtractTemporaryFile('isql.exe');
ExtractTemporaryFile('update_V42.sql');
if Exec(ExpandConstant('{tmp}') + '\isql.exe', '--user ' + DBPage.Values[2]
+ ' --password ' + DBPage.Values[3] + ' --database ' + DBPage.Values[0]
+ ':foo --script update_V42.sql', '',
SW_HIDE, ewWaitUntilTerminated, ResultCode)
then begin
// check ResultCode and set Result accordingly
Result := ResultCode = 0;
end else begin
MsgBox('Database update failed:'#10#10 + SysErrorMessage(ResultCode),
mbError, MB_OK);
Result := False;
end;
end;
end;
end;
Beware: I haven't fully tested this, so there may be more code necessary to properly clean everything up. Error handling is definitely missing!