T-SQL string email format issue - sql-server

I am trying to build an email and have run into an issue. When the stored procedure runs, I get the following error message.
Msg 14624, Level 16, State 1, Procedure sp_send_dbmail, Line 242
At least one of the following parameters must be specified. "#body,
#query, #file_attachments, #subject".
My code is below but I am adding each of the requested items. I have narrowed down where the breakdown happens. If I pull out the concatenation "+" everything works as expected. But I have done this before with the concatenation so I am not sure what is different.
DECLARE #RespPeriod varchar(20)
DECLARE #SubjectLine varchar(100)
DECLARE #ContactEmail varChar(100)
DECLARE #AAEAPVSupplierID int
DECLARE #key varchar(50)
DECLARE #formattedURL varchar(100)
DECLARE #emailBody varchar(max)
DECLARE Curs Cursor
FOR
SELECT theID FROM #temptbl
OPEN Curs
FETCH NEXT FROM Curs INTO #theID
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT *
INTO #temptbl
FROM tblmainTbl
WHERE theID = #theID
DECLARE #isComplete Bit = 1
IF EXISTS (SELECT * FROM #temptbl WHERE Complete = 0)
BEGIN
SET #isComplete = 0
END
IF #isComplete = 1
BEGIN
SET #SubjectLine = 'Testing ' + #RespPeriod + ' Testing.'
SET #ContactEmail = (SELECT SalesEmail FROM #temptbl WHERE theID = #theID)
SET #key = (SELECT ResponseKEY FROM #temptbl WHERE theID = #theID)
SET #formattedURL = 'http://www.something.com/something.aspx?rkey=' + #key
SET #emailBody = '<html>Dear BlaBlaBla' + #RespPeriod + ' ' + #formattedURL + '">' + #formattedURL + '</a></html>'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SMTPProfile'
,#recipients = #ContactEmail
,#subject = #SubjectLine
,#body = #emailBody
,#body_format = 'HTML'
END
DROP TABLE #temptbl
FETCH NEXT FROM Curs INTO #theID
END
CLOSE Curs
DEALLOCATE Curs

Your code sample is incomplete (you're lacking the declaration of some of the variables used). My hunch is one or more of the variable values (maybe #RespPeriod?) is NULL, and when you do the concatenations for the variable assignments used in your sp_send_dbmail call, you're passing NULL.
Remember, string + NULL = NULL
Right before your call to the sp_send_dbmail, insert these statements...
PRINT '--------------'
PRINT '#SubjectLine = ' + ISNULL(#SubjectLine, 'NULL')
PRINT '#ContactEmail = ' + ISNULL(#ContactEmail, 'NULL')
PRINT '#key = ' + ISNULL(#key, 'NULL')
PRINT '#formattedURL = ' + ISNULL(#formattedURL, 'NULL')
PRINT '#emailBody = ' + ISNULL(#emailBody, 'NULL')
PRINT '--------------'
It should quickly become apparent if this is your cause. If it is, chase back the individual parts of whatever variables are resolving as NULL until you find the piece that caused the entire string to be NULL. If it is not, please provide more code so we can look somewhere else.

Related

T-SQL context issue

I have created a script to compare the tables of two databases to find differences. I want to be able to manually set two variables (one for each database) and have the 'USE' statement use the variable value for one of the databases but it changes context and does work correctly.
This is what I am trying to use to populating a variable (#Use) with the USE code to execute
--set #Use = 'USE ' + #NewProdDB + ';SELECT name FROM sys.tables'
--EXEC (#Use)
This is the entire query:
--========================================================================================================
-- Used to find table values in the test upgrade system database not found the newly upgraded system
-- database. Make sure change the system database names before running the query.
-- Also, select the upgraded database to run against
--========================================================================================================
DECLARE #NewProdDB VARCHAR(100)
DECLARE #TestUpgradeDB VARCHAR(100)
DECLARE #Columns VARCHAR (MAX)
DECLARE #Query VARCHAR(MAX)
DECLARE #ResultsTest VARCHAR(MAX)
DECLARE #SetResultsCursor NVARCHAR(MAX)
DECLARE #Fetcher NVARCHAR(MAX)
DECLARE #Use NVARCHAR(50)
DECLARE #ListOfTables VARCHAR(100)
DECLARE #WTF NVARCHAR(max)
DECLARE #rescanCode nvarchar(max)
/* Enter Upgraded system DB here */
SET #NewProdDB = 'zSBSSYS'
/* Enter Test Upgrade system DB here */
SET #TestUpgradeDB = 'TESTzSBSSYS'
--set #Use = 'USE ' + #NewProdDB + ';SELECT name FROM sys.tables'
--EXEC (#Use)
SET NOCOUNT ON
set #rescanCode = 'DECLARE recscan CURSOR FOR
SELECT TABLE_NAME FROM ' + #TestUpgradeDB + '.INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME NOT LIKE ''Mbf%'' AND TABLE_TYPE = ''BASE TABLE''
ORDER BY TABLE_NAME'
exec (#rescanCode)
OPEN recscan
FETCH NEXT FROM recscan INTO #ListOfTables
WHILE ##fetch_status = 0
BEGIN
BEGIN TRY
/* START Table column query */
Declare #Table varchar(60)
set #Table = #ListOfTables
set #table = (SELECT top 1 name FROM sys.tables where name = #Table)
DECLARE
#sql1 nvarchar(max) = ''
,#INTOColumns NVARCHAR(MAX)=''
,#Where nvarchar(max) = ''
,#ColumnID Int
,#Column Varchar(8000)
,#Type Varchar(8000)
,#Length Int
,#del1 varchar(2) = ','
,#CRLF bit = 1
,#aliasfield varchar(5) = '[a].'
DECLARE CSR_Attributes CURSOR FOR
SELECT
[ColumnID] = Col.column_id,
[Column] = Col.Name,
[Type] = [types].name,
[Length] = Col.max_length
FROM sys.objects Obj, sys.columns Col, sys.types [types]
WHERE Obj.OBJECT_ID = Col.OBJECT_ID AND Obj.TYPE = 'U'
AND Col.system_type_id = [types].system_type_id
AND Obj.name = #table
AND Col.name <> 'tstamp'
ORDER BY Obj.name, Col.column_id, Col.name
OPEN CSR_Attributes
FETCH NEXT FROM CSR_Attributes INTO #ColumnID, #Column, #Type, #Length
WHILE ##FETCH_STATUS = 0
BEGIN
set #sql1 += #column + #del1
set #Where += 'b.' + #column + '=a.' + #column + ' and '
set #INTOColumns += '#INTOcol,'
FETCH NEXT FROM CSR_Attributes INTO #ColumnID, #Column, #Type, #Length
END
CLOSE CSR_Attributes
DEALLOCATE CSR_Attributes
SET #Columns = SUBSTRING(#sql1,1,len(#sql1)-1) -- get rid of last comma
SET #Where = SUBSTRING(#Where,1,len(#Where)-4) -- get rid of last 'and'
SET #INTOColumns = SUBSTRING(#INTOColumns,1,len(#INTOColumns)-1) -- get rid of last comma
/* END Table column query */
/* Create SELECT statement here */
SET #ResultsTest='SELECT TOP 1 ' + #Columns + '
FROM ' + #TestUpgradeDB + '..' + #Table + ' A
WHERE NOT EXISTS
(SELECT ' + #Columns + '
FROM ' + #NewProdDB + '..' + #Table + ' B WHERE ' + #Where + ')'
SET #SetResultsCursor = 'DECLARE DataReturned CURSOR FOR ' + #ResultsTest
exec (#SetResultsCursor)
OPEN DataReturned
SET #Fetcher = 'DECLARE #INTOcol NVARCHAR(Max)
FETCH NEXT FROM DataReturned INTO ' + #INTOColumns
exec (#Fetcher)
if ##FETCH_STATUS = 0
begin
CLOSE DataReturned
DEALLOCATE DataReturned
SET #Query='SELECT ' + #Columns + '
FROM ' + #TestUpgradeDB + '..' + #Table + ' A WHERE NOT EXISTS
(SELECT ' + #Columns + ' FROM ' + #NewProdDB + '..' + #Table + ' B WHERE ' + #Where + ')'
select #Table
exec (#Query)
end
else
begin
CLOSE DataReturned
DEALLOCATE DataReturned
end
end try
begin catch
--SELECT ERROR_MESSAGE() AS ErrorMessage;
end catch
FETCH NEXT FROM recscan INTO #ListOfTables
end
CLOSE recscan
DEALLOCATE recscan
SET NOCOUNT OFF
You can't do this:
DECLARE #DB varchar(10) = 'beep';
DECLARE #USE varchar(50) = 'USE '+ #DB;
EXEC sp_sqlexec #USE;
SELECT blah FROM bloop
Database context is only used during the #USE sql, then reverts
You can do this:
DECLARE #DB varchar(10) = 'beep';
DECLARE #SQL varchar(50) = 'USE '+#DB+'; SELECT blah FROM bloop;'
EXEC sp_sqlexec #USE;
That aside, look into SQL Server Data Tools (SSDT)
It does exactly what it seems you are trying to do, schema and/or data compare between databases, and it's very easy to use.

programmatically generate script for a table

I learned how to generate script for a table.
Eg for this table:
to generate script like this (I omitted something):
CREATE TABLE [dbo].[singer_and_album](
[singer] [varchar](50) NULL,
[album_title] [varchar](100) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[test_double_quote] ([singer], [album_title]) VALUES (N'Adale', N'19')
GO
INSERT [dbo].[test_double_quote] ([singer], [album_title]) VALUES (N'Michael Jaskson', N'Thriller"')
GO
I tried programmatically generating the script using this shell code. And got error:
PS
SQLSERVER:\SQL\DESKTOP-KHTRJOJ\MSSQL\Databases\yzhang\Tables\dbo.test_double_quote>
C:\Users\yzhang\Documents\script_out_table.ps1 "DESKTOP-KHTRJOJ\MSSQL"
"yzhang" "dbo" "test_double_quote",
"C:\Users\yzhang\Documents\script_out.sql"
Multiple ambiguous overloads found for "EnumScript" and the argument
count: "1". At C:\Users\yzhang\Documents\script_out_table.ps1:41
char:16
+ foreach ($s in $scripter.EnumScript($tbl.Urn)) { write-host $s }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Anybody can help? I don't know much about shell.
btw is shell the only way to generate scripts? Can we do it with some sql code? Thank you--
FYI, see this for how to manually generate script. In my case (sql server 2016 management studio) it's like
right click the database name (not table name) -> Tasks -> Generate scripts
choose a table or all tables
click advanced and select schema and data
this is a sql script to genrate table script
declare #vsSQL varchar(8000)
declare #vsTableName varchar(50)
select #vsTableName = '_PRODUCT'--- Your Table Name here
select #vsSQL = 'CREATE TABLE ' + #vsTableName + char(10) + '(' + char(10)
select #vsSQL = #vsSQL + ' ' + sc.Name + ' ' +
st.Name +
case when st.Name in ('varchar','varchar','char','nchar') then '(' + cast(sc.Length as varchar) + ') ' else ' ' end +
case when sc.IsNullable = 1 then 'NULL' else 'NOT NULL' end + ',' + char(10)
from sysobjects so
join syscolumns sc on sc.id = so.id
join systypes st on st.xusertype = sc.xusertype
where so.name = #vsTableName
order by
sc.ColID
select substring(#vsSQL,1,len(#vsSQL) - 2) + char(10) + ')'
Edit: c# code
public string GetScript(string strConnectionString
, string strObject
, int ObjType)
{
string strScript = null;
int intCounter = 0;
if (ObjType != 0)
{
ObjSqlConnection = new SqlConnection(strConnectionString.Trim());
try
{
ObjDataSet = new DataSet();
ObjSqlCommand = new SqlCommand("exec sp_helptext
[" + strObject + "]", ObjSqlConnection);
ObjSqlDataAdapter = new SqlDataAdapter();
ObjSqlDataAdapter.SelectCommand = ObjSqlCommand;
ObjSqlDataAdapter.Fill(ObjDataSet);
foreach (DataRow ObjDataRow in ObjDataSet.Tables[0].Rows)
{
strScript += Convert.ToString(ObjDataSet.Tables[0].Rows[intCounter][0]);
intCounter++;
}
}
catch (Exception ex)
{
strScript = ex.Message.ToString();
}
finally
{
ObjSqlDataAdapter = null;
ObjSqlCommand = null;
ObjSqlConnection = null;
}
}
return strScript;
}
To create Insert script use this store procedure
IF EXISTS (SELECT * FROM dbo.sysobjects
WHERE id = OBJECT_ID(N'[dbo].[InsertGenerator]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1)
DROP PROCEDURE [dbo].[InsertGenerator]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROC [dbo].[InsertGenerator]
(
#tableName varchar(100),
#KeyColumn1 varchar(100)='',
#KeyColumn2 varchar(100)=''
)
AS
-- Generating INSERT statements in SQL Server
-- to validate if record exists - supports 2 field Unique index
--Declare a cursor to retrieve column specific information for the specified table
DECLARE cursCol CURSOR FAST_FORWARD FOR
SELECT column_name,data_type FROM information_schema.columns WHERE table_name = #tableName
OPEN cursCol
DECLARE #string nvarchar(max) --for storing the first half of INSERT statement
DECLARE #stringData nvarchar(max) --for storing the data (VALUES) related statement
DECLARE #dataType nvarchar(1000) --data types returned for respective columns
DECLARE #FieldVal nvarchar(1000) -- save value for the current field
DECLARE #KeyVal nvarchar(1000) -- save value for the current field
DECLARE #KeyTest0 nvarchar(1000) -- used to test if key exists
DECLARE #KeyTest1 nvarchar(1000) -- used to test if key exists
DECLARE #KeyTest2 nvarchar(1000) -- used to test if key exists
SET #KeyTest0=''
IF #KeyColumn1<>''
SET #KeyTest0='IF not exists (Select * from '+#tableName
SET #KeyTest1=''
SET #KeyTest2=''
SET #string='INSERT '+#tableName+'('
SET #stringData=''
SET #FieldVal=''
SET #KeyVal=''
DECLARE #colName nvarchar(50)
FETCH NEXT FROM cursCol INTO #colName,#dataType
IF ##fetch_status<>0
begin
print 'Table '+#tableName+' not found, processing skipped.'
close curscol
deallocate curscol
return
END
WHILE ##FETCH_STATUS=0
BEGIN
IF #dataType in ('varchar','char','nchar','nvarchar')
BEGIN
SET #FieldVal=''''+'''+isnull('''''+'''''+'+#colName+'+'''''+''''',''NULL'')+'',''+'
SET #KeyVal='''+isnull('''''+'''''+'+#colName+'+'''''+''''',''NULL'')+'',''+'
SET #stringData=#stringData+#FieldVal
END
ELSE
if #dataType in ('text','ntext','xml') --if the datatype is text or something else
BEGIN
SET #FieldVal='''''''''+isnull(cast('+#colName+' as varchar(max)),'''')+'''''',''+'
SET #stringData=#stringData+#FieldVal
END
ELSE
IF #dataType = 'money' --because money doesn't get converted from varchar implicitly
BEGIN
SET #FieldVal='''convert(money,''''''+isnull(cast('+#colName+' as varchar(200)),''0.0000'')+''''''),''+'
SET #stringData=#stringData+#FieldVal
END
ELSE
IF #dataType='datetime'
BEGIN
SET #FieldVal='''convert(datetime,'+'''+isnull('''''+'''''+convert(varchar(200),'+#colName+',121)+'''''+''''',''NULL'')+'',121),''+'
SET #stringData=#stringData+#FieldVal
END
ELSE
IF #dataType='image'
BEGIN
SET #FieldVal='''''''''+isnull(cast(convert(varbinary,'+#colName+') as varchar(6)),''0'')+'''''',''+'
SET #stringData=#stringData+#FieldVal
END
ELSE --presuming the data type is int,bit,numeric,decimal
BEGIN
SET #FieldVal=''''+'''+isnull('''''+'''''+convert(varchar(200),'+#colName+')+'''''+''''',''NULL'')+'',''+'
SET #KeyVal='''+isnull('''''+'''''+convert(varchar(200),'+#colName+')+'''''+''''',''NULL'')+'',''+'
SET #stringData=#stringData+#FieldVal
END
--Build key test
IF #KeyColumn1=#colName
begin
SET #KeyTest1 = ' WHERE [' + #KeyColumn1 + ']='
SET #KeyTest1 = #KeyTest1+#KeyVal+']'
end
IF #KeyColumn2=#colName
begin
SET #KeyTest2 = ' AND [' + #KeyColumn2 + ']='
SET #KeyTest2 = #KeyTest2+#KeyVal+']'
end
SET #string=#string+'['+#colName+'],'
FETCH NEXT FROM cursCol INTO #colName,#dataType
END
DECLARE #Query nvarchar(max)
-- Build the test string to check if record exists
if #KeyTest0<>''
begin
if #Keycolumn1<>''
SET #KeyTest0 = #KeyTest0 + substring(#KeyTest1,0,len(#KeyTest1)-4)
if #Keycolumn2<>''
begin
SET #KeyTest0 = #KeyTest0 + ''''
SET #KeyTest0 = #KeyTest0 + substring(#KeyTest2,0,len(#KeyTest2)-4)
end
SET #KeyTest0 = #KeyTest0 + ''')'
SET #query ='SELECT '''+substring(#KeyTest0,0,len(#KeyTest0)) + ') '
end
else
SET #query ='SELECT '''+substring(#KeyTest0,0,len(#KeyTest0))
SET #query = #query + substring(#string,0,len(#string)) + ') '
SET #query = #query + 'VALUES(''+ ' + substring(#stringData,0,len(#stringData)-2)+'''+'')'' FROM '+#tableName
exec sp_executesql #query
CLOSE cursCol
DEALLOCATE cursCol
GO
and use of InsertGenerator like below
DECLARE #return_value int
EXEC #return_value = [dbo].[InsertGenerator]
#tableName = N'_PRODUCT'
SELECT 'Return Value' = #return_value

Msg 8169, Level 16, State 2, Line 52 Conversion failed when converting from a character string to uniqueidentifier

I am new to this SQL scripting.
Getting error while trying to execute a delete command.
Msg 8169, Level 16, State 2, Line 52 Conversion failed when converting
from a character string to uniqueidentifier.
And the script which I want to execute is:
-- attachments cleardown script
-- SJM 18/09/2009
set nocount on
declare #tableName nvarchar(200)
declare #columnName nvarchar(200)
declare #moduleName nvarchar(200)
declare #objectName nvarchar(200)
declare #attributeName nvarchar(200)
declare #dynamicSQL nvarchar(500)
declare #attachXML varchar(2000)
declare #fileGuid varchar(36)
declare #deletedXML varchar(100)
set #deletedXML = '<DataObjectAttachment><FileName>Deleted</FileName></DataObjectAttachment>'
declare attachCursor cursor fast_forward for
select t5.md_name, t4.md_name, t3.md_title, t2.md_title, t1.md_title
from md_attribute_type t1
join md_class_type t2 on t1.md_class_type_guid = t2.md_guid
join md_module t3 on t2.md_module_guid = t3.md_guid
join md_database_column t4 on t1.md_database_column_guid = t4.md_guid
join md_database_table t5 on t2.md_database_table_guid = t5.md_guid
where t1.md_data_type = 16 and (
t1.md_defined_by = 2 or
t1.md_guid in ('103DBEAB-252F-4C9A-952A-90A7800FFC00', '2515E980-788D-443D-AA89-AA7CC3653867',
'2D29495E-785E-4062-A49C-712A8136EBC7', '6A204C77-1007-48CC-B3BC-077B094540AE',
'9A24BFEF-2CAB-4604-8814-656BA0B9ECC3', 'C368CB18-B4C4-4C4F-839C-F7E6E1E17AA8',
'0814586B-A11E-4129-AF9B-9EC58120C9AF', 'BD4F73C4-07CA-4DC2-86AD-D713FBC6E7BA')
)
and t2.md_behaviour not in (2, 4, 8) -- exclude reference lists
and t2.md_guid not in (select b.md_class_type_guid from md_class_behaviour b where b.md_behaviour_type_guid in
(select bt.md_guid from md_behaviour_type bt where bt.md_name in ('Category','Ranked'))) -- exclude categories and ordered lists
and t3.md_name != 'Lifecycle'
order by t3.md_title, t2.md_title, t1.md_title
open attachCursor
fetch next from attachCursor into #tableName, #columnName, #moduleName, #objectName, #attributeName
while (##FETCH_STATUS = 0)
begin
print 'Deleting from ' + #moduleName + ' -> ' + #objectName + ' (' + #tableName + ') -> ' + #attributeName + ' (' + #columnName + ')...'
set #dynamicSQL = 'declare attachCursor1 cursor fast_forward for'
set #dynamicSQL = #dynamicSQL + ' select ' + #columnName + ' from ' + #tableName
set #dynamicSQL = #dynamicSQL + ' where ' + #columnName + ' != ''' + #deletedXML + ''''
exec sp_executesql #dynamicSQL
open attachCursor1
fetch next from attachCursor1 into #attachXML
while (##FETCH_STATUS = 0)
begin
set #fileGuid = substring(#attachXML, charindex('<Guid>', #attachXML) + 6, 36)
delete from tps_attachment_data where tps_guid = convert(uniqueidentifier, #fileGuid)
fetch next from attachCursor1 into #attachXML
end
close attachCursor1
deallocate attachCursor1
set #dynamicSQL = 'update ' + #tableName + ' set ' + #columnName + ' = ''' + #deletedXML + ''''
set #dynamicSQL = #dynamicSQL + ' where ' + #columnName + ' != ''' + #deletedXML + ''''
exec sp_executesql #dynamicSQL
print '- Deleted ' + convert(varchar(10),##Rowcount) + ' records.'
fetch next from attachCursor into #tableName, #columnName, #moduleName, #objectName, #attributeName
end
close attachCursor
deallocate attachCursor
set nocount off
print char(13) + 'Attachment cleardown complete.'
print char(13) + 'Next steps to reclaim data file space:'
print '1. Take a backup!'
print '2. Shrink the database using the command: DBCC SHRINKDATABASE(''' + convert(varchar(100),SERVERPROPERTY('ServerName')) + ''')'
print '3. Put the database into SINGLE_USER mode (Properties -> Options -> Restrict Access)'
print '4. Detach the database'
print '5. Rename the database .LDF log file'
print '6. Re-attach the database using single file method'
When I parse above script then it is completing successfully but on execution it throws the error.
There are two new functions that have been available since SQL Server 2012: TRY_CAST and TRY_CONVERT, which complement the existing CAST and CONVERT functions.
If you cast an empty string to a unique identifier:
SELECT CAST('' as uniqueidentifier) uid
This would result in the error you are seeing. The same would be true or other strings that aren't GUIDs. Use TRY_CAST instead and the function returns a NULL instead of throwing an error. You can then skip records that don't have a valid GUID.
begin
set #fileGuid = substring(#attachXML, charindex('<Guid>', #attachXML) + 6, 36)
DECLARE #fileGuidOrNull uniqueidentifier = try_convert(uniqueidentifier, #fileGuid)
IF #fileGuidOrNull IS NOT NULL
delete from tps_attachment_data where tps_guid = #fileGuidOrNull
fetch next from attachCursor1 into #attachXML
end

SQL Server Stored Procedure with cursor

I have following stored procedure which basically uses cursor to get people who have appointments today and sends them email. For some reason this query won't complete. When I try to execute it, it just spins and I had to stop it. I let it run for as long as 7 minutes once and still I didn't get either an error or timeout. Not sure what it is doing. Any help will be appreciated. Here is my query:
ALTER PROCEDURE [dbo].[spReminderEmail]
AS
SET NOCOUNT ON;
DECLARE #MyCursor CURSOR
DECLARE #emailBody nvarchar(max)
DECLARE #subject nvarchar(max)
DECLARE #recipients nvarchar(max)
DECLARE #appointmentDate datetime
DECLARE #doctorFirstName nvarchar(max)
DECLARE #doctorLastName nvarchar(max)
DECLARE #groupName nvarchar(max)
DECLARE #location nvarchar(max)
DECLARE #count int
SET #count = 0
SET #MyCursor = CURSOR FAST_FORWARD For
Select StartTime, PersonEmail, DoctorFirstName, DoctorLastName, GroupName, Location from vwAppointment where StartTime BETWEEN CAST(GETDATE() AS DATE) AND DATEADD(DAY, 1, CAST(GETDATE() AS DATE)) AND IsActive = 1
Open #MyCursor
FETCH NEXT FROM #MyCursor INTO #appointmentDate, #recipients, #doctorFirstName, #doctorLastName, #groupName, #location
WHILE ##FETCH_STATUS = 0
BEGIN
SET #emailBody = 'Hello from ' + #groupName + '. This is an email reminder of your appointment with ' + #doctorFirstName + ' ' + #doctorLastName + ' on ' + convert(varchar, #appointmentDate, 1) + ' at ' + #location + '.' + CHAR(13) + CHAR(10) + 'To help facilitate the meeting, please remember to bring with you any relevant documents (ID, insurance, etc.) and be prepared with questions for the office.' + CHAR(13) + CHAR(10) + 'If you are unable to make the appointment, please call ' + #groupName + ' or return to KSUAdvising and use the cancellation function. Cancellations are requested at least a day in advance.' + CHAR(13) + CHAR(10) + 'Late Policy:' + CHAR(13) + CHAR(10) + 'some text here...';
SET #subject = 'REMINDER: Your Appointment with the ' + #groupName;
SET #count = #count + 1
END
CLOSE #MyCursor
DEALLOCATE #MyCursor
PRINT #count
if (#count > 0)
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name='my_profile',
#recipients=#recipients,
#body=#emailBody,
#subject=#subject
END
Inside the WHILE loop (before END line) you must add this:
FETCH NEXT FROM #MyCursor INTO #appointmentDate, #recipients,
#doctorFirstName, #doctorLastName, #groupName, #location
to scroll for every loop a record of your query
You're never fetching your next row. So your loop will go on forever doing nothing. You need to add FETCH NEXT FROM #MyCursor INTO #appointmentDate, #recipients, #doctorFirstName, #doctorLastName, #groupName, #location right before your END statment . See the example at the bottom of This
You also may try to debug your sp to find exact place of issues in you SP in the future.

Msg 102, Level 15, State 1, Line 34 Incorrect syntax near '.'

I am getting above error while executing query as following, which is a stored procedure command line execution
exec sp_Bind_Division_Store_Camera_On_Filter_In_Liveview
null, null, null, null
Stored procedure is as following
ALTER PROCEDURE [dbo].[sp_Bind_Division_Store_Camera_On_Filter_In_Liveview]
#division varchar(45),
#store varchar(45),
#camera varchar(68),
#group varchar(100)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE
#BaseQuery nvarchar(max) = 'select
distinct tblcameradetails.name as CameraName,
tblcameradetails.IsDeviceEnabled,
tblcameradetails.cameraID,
tblcameradetails.deviceIP,
tblmediasourcedetails.StreamName,
tblmediasourcedetails.streamID,
tblcameradetails.Model_ID,
tblcameradetails.IsHidden,
tblcameradetails.hasPTZcapability,
tblcameradetails.CameraModelNo,
tblcameradetails.username as CameraUserName,
tblcameradetails.hasPTZCycle,
tblcameradetails.hasPreset,
tblcameradetails.password as CameraPassword,
tblmediasourcedetails.isRecordingStarted as IsRecordingOn,
tblcameradetails.IsCovert,
tblcameradetails.constCameraName,
tblmediasourcedetails.constStreamName,
tblstoredetails.Store_ID,
tblsystemlocationdetails.division,
tblstoredetails.Store_Name,
tblstoredetails.Store_IP,
tblstoreconfiguration.Liveview_Session_Timeout
from
tblmediasourcedetails,
tblcameradetails,
tblcameragroupdetails,
tblgroupdetails,
tblvssaddsourcedetails,
tblsystemlocationdetails,
tblstoredetails,
tblstoreconfiguration'
, #ParamList nvarchar(max) = N'#p1 varchar(45), #p2 varchar(45), #p3 varchar(68), #p4 varchar(100)'
, #WhereClause nvarchar(max) = N'where
tblmediasourcedetails.cameraID=tblcameradetails.cameraID
and tblmediasourcedetails.streamID=tblvssaddsourcedetails.streamID
and tblcameradetails.cameraID = tblcameragroupdetails.cameraID
and tblcameragroupdetails.groupID=tblgroupdetails.groupID
and tblstoredetails.Store_ID= tblcameradetails.Store_ID
and tblsystemlocationdetails.Store_ID= tblstoredetails.Store_ID
and tblstoredetails.Store_ID=tblstoreconfiguration.Store_ID and 1=1'
, #OrderByClause nvarchar(100) = 'order by CameraName';
IF #division IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' and division like (#p1)';
END
IF #store IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' and (store like (#p2))';
END
IF #camera IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' and tblcameradetails.name like (#p3)';
END
IF #group IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' and tblgroupdetails.name in (#p4)';
END
SET #BaseQuery = #BaseQuery + #WhereClause + #OrderByClause;
EXECUTE sp_executesql #BaseQuery, #ParamList, #p1 = #division, #p2 = #store, #p3 = #camera, #p4 = #group;
END
Now error shows me that on line 34 error at syntax near '.', but I found no problem at all, because I am run this query form command prompt very well same applied in stored procedure, it will raised error. Please help me to solved out this.
You can easily print your variable #BaseQuery to check the resulting query.
the query in the variable #BaseQuery looks like this
select
distinct tblcameradetails.name as CameraName,
tblcameradetails.IsDeviceEnabled,
tblcameradetails.cameraID,
tblcameradetails.deviceIP,
tblmediasourcedetails.StreamName,
tblmediasourcedetails.streamID,
tblcameradetails.Model_ID,
tblcameradetails.IsHidden,
tblcameradetails.hasPTZcapability,
tblcameradetails.CameraModelNo,
tblcameradetails.username as CameraUserName,
tblcameradetails.hasPTZCycle,
tblcameradetails.hasPreset,
tblcameradetails.password as CameraPassword,
tblmediasourcedetails.isRecordingStarted as IsRecordingOn,
tblcameradetails.IsCovert,
tblcameradetails.constCameraName,
tblmediasourcedetails.constStreamName,
tblstoredetails.Store_ID,
tblsystemlocationdetails.division,
tblstoredetails.Store_Name,
tblstoredetails.Store_IP,
tblstoreconfiguration.Liveview_Session_Timeout
from
tblmediasourcedetails,
tblcameradetails,
tblcameragroupdetails,
tblgroupdetails,
tblvssaddsourcedetails,
tblsystemlocationdetails,
tblstoredetails,
tblstoreconfigurationwhere
tblmediasourcedetails.cameraID=tblcameradetails.cameraID
and tblmediasourcedetails.streamID=tblvssaddsourcedetails.streamID
and tblcameradetails.cameraID = tblcameragroupdetails.cameraID
and tblcameragroupdetails.groupID=tblgroupdetails.groupID
and tblstoredetails.Store_ID= tblcameradetails.Store_ID
and tblsystemlocationdetails.Store_ID= tblstoredetails.Store_ID
and tblstoredetails.Store_ID=tblstoreconfiguration.Store_ID and 1=1order by CameraName
You can see that you are missing a space before the WHERE and ORDER BY clause
You need to add a space in the starting of your WHERE and ORDER BY variables like this
#WhereClause nvarchar(max) = N' where
#OrderByClause nvarchar(100) = ' order by CameraName';
Try to put some PRINT in the middle of the query.
For example PRINT #BaseQuery after SET #BaseQuery = #BaseQuery + #WhereClause + #OrderByClause;
Because maybe you need a space in some variable (for example N' where...1=1' instead of N'where...1=1' )

Resources