Query result to xlsx and send mail in SQL Server - sql-server

There is a procedure in which an Excel file is created, the result of the selection is saved in it. This file is attached to the letter and sent by mail. But the problem is that the file is created and sent empty. Manually everything works, but not together.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_sendMail]
#SID INT,
#EMAIL VARCHAR(512),
#CUR INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#MAILID INT,
#TABLEHTML VARCHAR(MAX),
#CMD SYSNAME,
#FILENAME NVARCHAR(MAX),
#SQL NVARCHAR(MAX),
#PID INT,
#DATE_START DATE,
#DATE_END DATE
SELECT
#PID = PATIENTS_ID,
#DATE_START = DATE_START,
#DATE_END = DATE_END
FROM
TABLE
WHERE
ID = #SID
EXEC SP_EXECUTESQL N'sp_configure ''show advanced options'', 1; reconfigure; '
EXEC ('RECONFIGURE')
EXEC SP_EXECUTESQL N'sp_configure ''xp_cmdshell'', 1; reconfigure;'
EXEC ('RECONFIGURE')
SET #FILENAME = 'D:\' + CAST(#SID AS VARCHAR) + '_' + REPLACE(CONVERT(VARCHAR, GETDATE(), 104), '.', '') + '_' + CAST(#CUR AS VARCHAR) + '.xlsx'
SET #CMD = 'copy D:\Example.xlsx ' + #FILENAME
EXEC MASTER..XP_CMDSHELL #CMD;
SET #SQL = 'INSERT INTO OPENROWSET(''Microsoft.ACE.OLEDB.12.0'',
''Excel 12.0;Database=' + #FILENAME + ';HDR=YES'',
''SELECT DATE, CODE, LABEL, CNT, CU, SCO, DISCOUNT FROM [Sheet1$]'')
SELECT
CONVERT(VARCHAR, ORDER.DATE, 104) DATE,
EMPLOYEE.CODE CODE,
EMPLOYEE.LABEL LABEL,
CAST(ORDER.CNT AS INT) CNT,
CAST(ORDER.PRICE AS MONEY) CU,
CAST(ORDER.PRICE_TO_PAY AS MONEY) SCO,
CAST(ORDER.DISCOUNT AS INT) DISCOUNT
FROM
ORDER
JOIN
EMPLOYEE ON EMPLOYEE._ID = ORDER._ID
WHERE
(CONVERT(DATE, ORDER.DATE) >= CONVERT(DATE, #DATE_START)
AND CONVERT(DATE, ORDER.DATE) <= CONVERT(DATE, #DATE_END))
AND (ORDER.ID in (#PID))
ORDER BY ORDER.DATE'
EXEC SP_EXECUTESQL
#SQL,
N'#DATE_START DATE, #DATE_END DATE, #PATID INT',
#DATE_START = #DATE_START,
#DATE_END = #DATE_END,
#PID = #PID
SET #TABLEHTML =
N'<H1>Hello!</H1>' +
N'<span>num: </span>' + CAST(#SID AS VARCHAR(MAX)) +
N'<span>, email: </span>' + CAST(#EMAIL AS VARCHAR(MAX)) +
N'<span> sent! </span>'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'site.com',
#recipients = 'admin#site.com',
#subject = 'subj',
#body = #tableHTML,
#body_format = 'HTML',
#file_attachments = #FILENAME,
#mailitem_id = #mailid output
IF (#MAILID > 0 AND ##ERROR = 0)
UPDATE TABLE SET [SIGN] = 1, [SENT] = GETDATE(), SENDER = #CUR WHERE ID = #SID
EXEC SP_EXECUTESQL N'sp_configure ''show advanced options'', 1; reconfigure; '
EXEC ('RECONFIGURE')
EXEC SP_EXECUTESQL N'sp_configure ''xp_cmdshell'', 0; reconfigure;'
EXEC ('RECONFIGURE')
END

Yes, JGFMK was right!
If execute this code, then openrowset will be done:
if( 1 = 0)
begin
INSERT INTO OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0;Database=D:\file;HDR=YES',
'SELECT DATE, CODE, LABEL, CNT, CU, SCO, DISCOUNT FROM [Sheet1$]')
SELECT..
end
How to make it work by condition ?

Related

Limiting SQL Server Transaction log

I currently have a SQL script that takes all the tables with a certain name and deletes records from it.
There are millions of records in these tables so the transaction log keeps growing even with recovery set to SIMPLE. I am putting the delete in side a transaction and it's only deleting around 50000 records at a time. Can anyone suggest some way to not let the transaction log grow uncontrollably. Below is the rough example of the SQL I am running.
DECLARE delete_cur CURSOR FOR
SELECT DISTINCT Name FROM Sys.tables WHERE name like 'ToDelete_%'
OPEN delete_cur
FETCH NEXT FROM delete_cur
INTO #tableName
WHILE ##FETCH_STATUS = 0 AND #timeToStop = 0
BEGIN
SELECT #RowCount = NULL, #MaxID = NULL, #MinID = NULL, #ID = NULL, #TableRowCount = 0
IF NOT Exists (Select 1 from ArchiveInfoAuditTables WHERE Name = #tableName)
BEGIN
SET #params = N'#MaxID_Out DECIMAL(18,0) OUT, #MinID_Out DECIMAL(18,0) OUT, #RowCount_Out DECIMAL(18,0) OUT';
SET #SQL = 'SELECT #RowCount_Out = COUNT(ID), #MaxID_Out = MAX(ID), #MinID_Out = MIN(ID) FROM ' + #tableName
print #SQL
EXEC sp_executesql #SQL, #params, #RowCount_Out = #RowCount OUT, #MaxID_Out = #MaxID OUT, #MinID_Out = #MinID OUT;
PRINT #tableName + ' Row Count: ' + CONVERT(VARCHAR, #RowCount) + ' Max ID: ' + CONVERT(VARCHAR, #MaxID) + ' Min ID: ' + CONVERT(VARCHAR, #MinID)
SET #params = N'#ID_Out DECIMAL(18,0) OUT, #Date DATETIME';
SET #SQL = 'SELECT TOP 1 #ID_Out = ID FROM ' + #tableName + ' WHERE AuditTimeStamp < #Date ORDER BY ID DESC'
print #SQL
EXEC sp_executesql #SQL, #params, #ID_Out = #ID OUT, #Date = #JanOfCurrentYear
INSERT INTO DeleteInfo (Name, StartDeletingFromID, MaxID, MinID, NumberOfRows)
VALUES (#tableName, #ID, #MaxID, #MinID, #RowCount)
END
ELSE
BEGIN
SELECT TOP 1 #ID = StartDeletingFromID FROM DeleteInfo WHERE Name = #tableName
END
IF (#ID IS NULL)
BEGIN
PRINT 'No Record needs to be deleted for Table: ' + #tableName
GOTO Fetch_Next
END
WHILE 1 = 1
BEGIN
BEGIN TRANSACTION
SET #params = N'#RowCount_Out DECIMAL(18,0) OUT, #NumOfRowsToDelete_Out BIGINT, #ID_Out DECIMAL(18,0)'
SET #SQL = 'DELETE TOP (#NumOfRowsToDelete_Out) FROM ' + #tableName + ' WHERE ID <= #ID_Out ;'
+ 'SELECT #RowCount_Out = ##RowCount'
PRINT #SQL
EXEC sp_executesql #SQL, #params, #RowCount_Out = #TempRowCount OUT, #NumOfRowsToDelete_Out = #NumOfRowsToDelete, #ID_Out = #ID
SET #TableRowCount += #TempRowCount
SET #TotalRowCount += #TableRowCount
COMMIT TRANSACTION
CHECKPOINT;
SET #MSG = 'Deleted ' + CAST(#TableRowCount AS VARCHAR) + '. ' + CONVERT(varchar, #TimeElapsed) + ' elapsed.'
RAISERROR (#MSG, 0, 1) WITH NOWAIT
IF #TempRowCount < #NumOfRowsToDelete BREAK;
END
Fetch_Next:
PRINT '/******************************************************************/'
FETCH NEXT FROM delete_cur
INTO #tableName
END
END_HERE:
CLOSE delete_cur;
DEALLOCATE delete_cur;
You can limit the size of the log (here we limit the size to 512 MB):
ALTER DATABASE [DatabaseName] MODIFY FILE ( NAME = N'DATABASENAME_Log', SIZE = 512000KB , FILEGROWTH = 0)
Create a maintenance job for backups the DB and shrinks the log
you can use this simple command to shrink the log file
DBCC SHRINKFILE (DataFile1, 512)

Stored Procedure if Exist with dynamically table

I have a problem here, I'm searching in stackoverflow but still not find the best way
i have a stored procedure (SP) like this
DECLARE #table NVARCHAR(max), #SQLQuery NVARCHAR(max)
SET #table = #meta+'_prize4winner'
SET #SQLQuery = 'if exists (Select * from [dbo].' + #table + ' where idCampaignLog =''' + convert(nvarchar, #ID) +''') exec InsertC2CWinner''' + convert(nvarchar, #meta) +''','''+ convert(nvarchar, #ID)+''',null else select ''you lose ''as winStatus'
execute SP_EXECUTESQL #SQLQuery
need help how and where to set the output if I want the output if exist 'YOU WIN' else 'You Lose' thx
The general syntax is like this
DECLARE #retval int
DECLARE #sSQL nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
DECLARE #tablename nvarchar(50)
SELECT #tablename = N'products'
SELECT #sSQL = N'SELECT #retvalOUT = MAX(ID) FROM ' + #tablename;
SET #ParmDefinition = N'#retvalOUT int OUTPUT';
EXEC sp_executesql #sSQL, #ParmDefinition, #retvalOUT=#retval OUTPUT;
SELECT #retval;

MSSQL stored procedure call from ADO - not running properly

I have sp in MSSQL server - code below. When I run it from job, or SSMS it runs OK. But I need to run it from VB6 app with ADODB.
My VB6 code:
Dim cmd As New ADODB.Command
cmd.ActiveConnection = CNN
cmd.CommandTimeout = 180
cmd.CommandText = "dbbackup"
cmd.CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
cmd.Execute(, , ADODB.ConnectOptionEnum.adAsyncConnect)
Problem is: When database backup is almost done - about 90+%, cmd.State changes from Executing to Closed and VB6 code continue in executing (to this moment it waits for sp to complete). But there is a lot of code after backup which never run this way(old backup delete,...). I realized that “Last database backup” property on MSSQL database was not set and in table msdb.dbo.backupset there are no rows for my backup. But there si good restorable backup on HDD.
When i stops program for 5 minutes in debug, sp runs properly to end and everything is OK. This backup code is last code in app run and after it ends program closes all connections and exits. I added wait to VB6 code and it helps on some servers, but many other servers still has same problem.
I think main question is why MSSQL server returns control flow to VB6 code and sp is not completed yet.
Thanks
sp code:
PROCEDURE [dbo].[dbBackup]
AS
BEGIN
SET NOCOUNT ON;
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
If OBJECT_ID('tempdb..#DBName','u') IS NULL
Create Table #DBName
(
ID int identity (1,1) ,
Name varchar(128) not null ,
RetentionPeriod int null,
BackupPath varchar(255) default(''),
DBSize float default(0)
)
If OBJECT_ID('tempdb..#ExistingBackups', 'u') IS NULL
Create Table #ExistingBackups
(
Name varchar(128) ,
ID int identity (1,1)
)
Declare #Path varchar(255)
Declare #sql varchar(1000)
Declare #Name varchar(128)
Declare #RetentionPeriod int
Declare #LastBackupToKeep varchar(8)
Declare #ID int
Declare #MaxID int
Declare #eName varchar(255)
Declare #eMaxID int
Declare #eID int
Declare #eTimeStamp varchar(20)
Declare #errMsg nvarchar(2048)
Declare #errCount int; set #errCount = 0;
Declare #freeSpace bigint
Declare #pageSize float
Declare #dbSize bigint
Declare #procDate datetime
Declare #Sklad char(3)
Declare #backupName as varchar(255)
Select #pageSize = v.low / 1024 From master..spt_values v (noLock) Where v.number = 1 And v.[type] = 'E'
Select Top 1 #sklad = sklad_id From dbo.pohyb (noLock) Where Convert(int, sklad_id) > 500
Set #procDate = GETDATE()
Truncate Table #DBName
Insert Into #DBName (Name, RetentionPeriod, BackupPath)
Select DBName, BackupsToStore, BackupPath
From dbo.databaseBackup (noLock)
Where runBackup = 1
Select #MaxID = max(ID), #ID = 0 From #DBName
While #ID < #MaxID
Begin
Select #ID = min(ID) From #DBName Where ID > #ID
Select #Name = Name, #RetentionPeriod = RetentionPeriod, #Path = BackupPath
From #DBName
Where ID = #ID
If SUBSTRING(#Path, Len(#Path), 1) <> '\' Set #Path = #Path + '\'
Set #sql = 'Update #DBName Set DBSize= (Select Round(Sum(size) *' + CONVERT(varchar, #pageSize) + '/1024, 0) From ' + #Name + '.dbo.sysfiles (noLock)) Where Name = ''' + #Name + ''''
Exec (#sql)
Select #dbSize = DBSize From #DBName
--Exec #freeSpace = dbo.getDiskFreeSpace #drive = #Path
--If #freeSpace > #dbSize
--Begin
Set #eTimeStamp = REPLACE(REPLACE(CONVERT(varchar, #procDate, 113), ' ', '_'), ':', '-')
Set #sql = #Path + #Name + '_' + #eTimeStamp + '.bak'
Set #errMsg = 'OK'
Begin Try
SET #backupName = 'Objednavky backup by job ' + CONVERT(varchar, GETDATE(), 104) + ' ' + CONVERT(varchar, GETDATE(), 108);
Backup Database #Name To Disk = #sql
WITH NAME = #backupName;
-------mazanie backupu begin
Truncate Table #ExistingBackups
Set #sql = 'dir /B /OD ' + #Path + #Name + '_*.bak'
Insert #ExistingBackups Exec master..xp_cmdshell #sql
If Exists (Select 1 From #ExistingBackups Where PATINDEX('%File Not Found%', Name) > 0)
Truncate Table #ExistingBackups
Delete From #ExistingBackups Where Name IS NULL
Select #eID = 0
Select #eMaxID = Max(ID) - #RetentionPeriod From #ExistingBackups
While #eID < #eMaxID
Begin
Select #eID = Min(ID) From #ExistingBackups Where ID > #eID
Select #eName = Name From #ExistingBackups Where ID = #eID
Set #sql = 'del ' + #Path + #eName
Exec master..xp_cmdshell #sql
End
Truncate Table #ExistingBackups
-------mazanie backupu end
End Try
Begin Catch
Set #errMsg = #errMsg + '||' + CONVERT(varchar,ERROR_MESSAGE())
Set #errCount = #errCount + 1;
End Catch
--End
--Else
--Set #errMsg = 'Pln? disk (Vo?n? miesto: ' + CONVERT(varchar, #freeSpace) + ' MB, potrebn? aspo?: ' + CONVERT(varchar, #dbSize) + ' MB)'
Insert Into [dbo].[databaseBackup_log] ([Sklad_id], [DBName], [BackupDate], [Status]) Values (#Sklad, #Name, #procDate, Ltrim(Rtrim(CONVERT(varchar,#errMsg))))
End
Drop Table #DBName
Drop Table #ExistingBackups
IF #errCount > 0 BEGIN
RAISERROR (#errMsg, 16, 2) WITH SETERROR
END
RETURN 0;
END

Passing negative values into stored procedure

I am trying to insert ID values in stored procedure from .net and the int value for ID is inserting negative value in the stored procedure.
But when a negative value is passed its giving me an error incorrect syntax near '*'.
Please help me.
Here is my stored procedure
ALTER PROCEDURE [dbo].[HotlinePlusAdministration_ArticleMigrator]
#Id AS INT,
--#CategoryID AS INT,
--#Title AS Varchar(200),
--#ArticleDate AS datetime,
#DestLinkServer AS VARCHAR(50),
#UserID AS VARCHAR(8),
#ReturnMsg AS VARCHAR(1000) OUTPUT
AS
BEGIN
DECLARE #Query AS NVARCHAR(4000)
DECLARE #Log AS VARCHAR(8000)
DECLARE #ArticleID as int
DECLARE #NewArticleID as int
DECLARE #ArticleKeyExists as int
DECLARE #Title as varchar(200)
DECLARE #CategoryID as INT
DECLARE #ArticleDate as varchar(30)
DECLARE #ParmDefinition nvarchar(500);
SET XACT_ABORT ON -- Required for nested transaction
BEGIN TRAN
-- Check if ArticleID exists in Destination Server
SET #Query = N' SELECT #ArticleKeyExists = COUNT(*)
FROM ' + #DestLinkServer + '.HL2_61.dbo.Article' + ' where ArticleKey = ' + str(#Id)
SET #ParmDefinition = N' #ID int, #ArticleKeyExists int OUTPUT';
EXECUTE sp_executesql #Query , #ParmDefinition, #ID, #ArticleKeyExists OUTPUT;
--EXECUTE sp_executesql 1234,'BRHLSQL8','BRWSQLDC',#return = retnmsg
IF ##ERROR <> 0
BEGIN
ROLLBACK TRANSACTION
SET #ReturnMsg = #Log + '<span style="color:red;">ERROR: <br></span>'
RETURN -1
END
--Delete existing Articles for select page
set #Query = 'DELETE FROM ' + #DestLinkServer +
'.HL2_61.dbo.Article ' +
'WHERE ArticleKey = ' + CONVERT(VARCHAR, #Id)
--'WHERE CategoryID = ' + CONVERT(VARCHAR, #CategoryID) + ' and Title = ''' + #Title + ''' and ArticleDate = ''' + #ArticleDate + ''''
Print #Query
EXEC(#Query)
When I am executing the code as below I am getting the error.
DECLARE #return_value int,
#ReturnMsg varchar(1000)
EXEC #return_value = [dbo].[Migrator]
#Id = -1591276581,
#DestLinkServer = N'SQLDC',
#UserID = N'10c1',
#ReturnMsg = #ReturnMsg OUTPUT
SELECT #ReturnMsg as N'#ReturnMsg'
SELECT 'Return Value' = #return_value
GO
Please someone help me..
Thanks
When you convert an int to a varchar, you have to specify the size:
Try this:
CONVERT(VARCHAR(50), #Id)
and avoid using str(#Id)

incorrect syntax near '*'

I was trying to execute one of my Stored procedure but i am getting an syntax error and i am unable to understand why.
here is the sproc:
ALTER PROCEDURE [dbo].[HotlinePlusAdministration_ArticleMigrator]
#ArticleKey AS INT,
--#CategoryID AS INT,
--#Title AS Varchar(200),
--#ArticleDate AS datetime,
#DestLinkServer AS VARCHAR(50),
#UserID AS VARCHAR(8),
#ReturnMsg AS VARCHAR(1000) OUTPUT
AS
BEGIN
DECLARE #Query AS NVARCHAR(4000)
DECLARE #Log AS VARCHAR(8000)
DECLARE #ArticleID as int
DECLARE #NewArticleID as int
DECLARE #ArticleKeyExists as int
DECLARE #Title as varchar(200)
DECLARE #CategoryID as INT
DECLARE #ArticleDate as varchar(30)
DECLARE #ParmDefinition nvarchar(500);
SET XACT_ABORT ON -- Required for nested transaction
BEGIN TRAN
-- Check if ArticleID exists in Destination Server
SET #Query = N' SELECT #ArticleKeyExists = COUNT(*)
FROM ' + #DestLinkServer + '.HL2_61.dbo.Article' + ' where ArticleKey = ' + str(#ArticleKey)
SET #ParmDefinition = N'#ArticleKey int, #ArticleKeyExists int OUTPUT';
EXECUTE sp_executesql #Query , #ParmDefinition, #ArticleKey , #ArticleKeyExists OUTPUT;
IF ##ERROR <> 0
BEGIN
ROLLBACK TRANSACTION
SET #ReturnMsg = #Log + '<span style="color:red;">ERROR: <br></span>'
RETURN -1
END
--Delete existing Articles for select page
set #Query = 'DELETE FROM ' + #DestLinkServer +
'.HL2_61.dbo.Article ' +
'WHERE ArticleKey = ' + CONVERT(VARCHAR, #ArticleKey)
--'WHERE CategoryID = ' + CONVERT(VARCHAR, #CategoryID) + ' and Title = ''' + #Title + ''' and ArticleDate = ''' + #ArticleDate + ''''
Print #Query
EXEC(#Query)
when i am trying to execute it i am getting an error here:
SELECT #ArticleKeyExists = COUNT(*)
FROM BRWSQLDC.HL2_61.dbo.Article where ArticleKey = 1591276581
Can some body please help me on this,
Thanks.
SET #ArticleKeyExists = (SELECT COUNT(*) FROM BRWSQLDC.HL2_61.dbo.Article where ArticleKey = 1591276581)

Resources