May 17, 2017 at 8:11 am
I need to dynamically search a folder on a local drive and load the file names into a string and then have the sp_send_dbmail set those attached files out in an email.
If I create a cursor and go through each file name and load that file_name into a string and do the sp_send_dbmail, the process fails with the error:
Msg 22051, Level 16, State 1, Line 0
Attachment file 'S:\Reports\List_Remote_Databases_V_05-16-2017.xls is invalid.
But can take that exact string and run sp_send_dbmail manually and it works just fine.
Here is what I have that works.
@file_attachments='S:\Reports\List_Remote_Databases_V_05-16-2017.xls;S:\Reports\MatrixTbl_V1_05-16-2017.xls;S:\Reports\Sum_Server_Inst_V_05-16-2017.xls;S:\Reports\Sum_Srv_Inst_DB_Clust_TBL_V_05-16-2017.xls;S:\Reports\Sum_Srv_Space_Used_V_05-16-2017.xls;S:\Reports\Sum_Version_TBL_V_05-16-2017.xls'
I took the file list from the string that is created dynamically.
May 17, 2017 at 3:20 pm
Is S: a mapped drive or a local drive? Is this run as a SQL Agent Job? If so, does the account it runs under have permissions on that path? How are you getting the file list?
May 17, 2017 at 4:25 pm
I see you've found the "feature" where you can't have a space after your semicolon-delimited list of filenames, so that's good.
Joe's probably right - it looks like a permissions problem. If it runs for you, then you know the code's solid. Take a look at the permissions (including file system permissions) that it runs as when it fails. The answer is probably there.
May 18, 2017 at 7:24 am
Joe Torre - Wednesday, May 17, 2017 3:19 PMIs S: a mapped drive or a local drive? Is this run as a SQL Agent Job? If so, does the account it runs under have permissions on that path? How are you getting the file list?
The S: is a local drive. I ran both of these manually. I have not yet set up the job to run from SQL Agent. I am getting the file list as this:
declare @files table (ID int IDENTITY, FileName varchar(100))
DECLARE @id_hold nvarchar(250),
@id_max nvarchar(250),
@file_names nvarchar(2000),
@file_dir nvarchar(250),
@first_file nvarchar(250)
select @file_dir = 'S:\Reports\'
insert into @files execute xp_cmdshell 'dir S:\Reports /b'
insert into [dbo].[SUM_MAIL_REPORTS]
([FILE_ID],[FILE_NAME],[CRDate])
select ID, FileName ,getdate() from @files
delete [dbo].[SUM_MAIL_REPORTS]
WHERE FILE_NAME = 'Backups'
OR FILE_NAME is null
select * from [dbo].[SUM_MAIL_REPORTS]
Select @id_hold = min(FILE_NAME), @id_max = max(FILE_NAME)
from [dbo].[SUM_MAIL_REPORTS]
WHERE CAST(CRDate AS DATE) > CAST((GETDATE()-2) AS DATE)
select @first_file = 'YES'
DECLARE db_cursor CURSOR FOR
SELECT FILE_NAME
FROM [MonitorDb].[dbo].[SUM_MAIL_REPORTS]
WHERE CAST(CRDate AS DATE) > CAST((GETDATE()-2) AS DATE)
ORDER BY FILE_NAME
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @id_hold
WHILE @@FETCH_STATUS = 0
BEGIN
IF @first_file = 'YES'
BEGIN
select @file_names = ''''+@file_dir+@id_hold
SELECT @first_file='NO'
END
ELSE
select @file_names = @file_names + ';'+@file_dir+@id_hold
select @file_names
FETCH NEXT FROM db_cursor INTO @id_hold
END
-- finish the string
CLOSE db_cursor
DEALLOCATE db_cursor
select @file_names = @file_names + ''''
--select @file_names
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'DBMailProfile'
, @recipients = 'lyle.nielsen@hsc.utah.edu'
, @subject = 'test attachment'
, @body = 'An attachment'
, @file_attachments=@file_names
select @file_names
May 18, 2017 at 8:38 am
lyle.nielsen 31819 - Thursday, May 18, 2017 7:24 AMJoe Torre - Wednesday, May 17, 2017 3:19 PMIs S: a mapped drive or a local drive? Is this run as a SQL Agent Job? If so, does the account it runs under have permissions on that path? How are you getting the file list?The S: is a local drive. I ran both of these manually. I have not yet set up the job to run from SQL Agent. I am getting the file list as this:
declare @files table (ID int IDENTITY, FileName varchar(100))
DECLARE @id_hold nvarchar(250),
@id_max nvarchar(250),
@file_names nvarchar(2000),
@file_dir nvarchar(250),
@first_file nvarchar(250)select @file_dir = 'S:\Reports\'
insert into @files execute xp_cmdshell 'dir S:\Reports /b'
insert into [dbo].[SUM_MAIL_REPORTS]
([FILE_ID],[FILE_NAME],[CRDate])
select ID, FileName ,getdate() from @filesdelete [dbo].[SUM_MAIL_REPORTS]
WHERE FILE_NAME = 'Backups'
OR FILE_NAME is nullselect * from [dbo].[SUM_MAIL_REPORTS]
Select @id_hold = min(FILE_NAME), @id_max = max(FILE_NAME)
from [dbo].[SUM_MAIL_REPORTS]
WHERE CAST(CRDate AS DATE) > CAST((GETDATE()-2) AS DATE)select @first_file = 'YES'
DECLARE db_cursor CURSOR FOR
SELECT FILE_NAME
FROM [MonitorDb].[dbo].[SUM_MAIL_REPORTS]
WHERE CAST(CRDate AS DATE) > CAST((GETDATE()-2) AS DATE)
ORDER BY FILE_NAMEOPEN db_cursor
FETCH NEXT FROM db_cursor INTO @id_holdWHILE @@FETCH_STATUS = 0
BEGIN
IF @first_file = 'YES'
BEGIN
select @file_names = ''''+@file_dir+@id_hold
SELECT @first_file='NO'
END
ELSE
select @file_names = @file_names + ';'+@file_dir+@id_hold
select @file_names
FETCH NEXT FROM db_cursor INTO @id_hold
END
-- finish the stringCLOSE db_cursor
DEALLOCATE db_cursorselect @file_names = @file_names + ''''
--select @file_names
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'DBMailProfile'
, @recipients = 'lyle.nielsen@hsc.utah.edu'
, @subject = 'test attachment'
, @body = 'An attachment'
, @file_attachments=@file_namesselect @file_names
Would something like this work for you? It would be a whole lot simpler to maintain and troubleshoot.
DECLARE @files TABLE (
ID Integer IDENTITY,
Filename Varchar(100));
DECLARE @file_names Varchar(MAX) = '';
INSERT INTO @files(Filename)
EXECUTE xp_cmdshell 'dir S:\Reports /b';
SELECT @file_names = @file_names + ';S:\Reports\' + Filename
FROM @files
WHERE NOT Filename = 'BACKUP'
AND Filename IS NOT NULL;
SELECT @file_names = STUFF(@file_names, 1, 1, '');
The only thing you would have left to do is populate your dbo.SUM_MAIL_REPORTS table.
May 18, 2017 at 9:09 am
Ed Wagner - Thursday, May 18, 2017 8:38 AMlyle.nielsen 31819 - Thursday, May 18, 2017 7:24 AMJoe Torre - Wednesday, May 17, 2017 3:19 PMIs S: a mapped drive or a local drive? Is this run as a SQL Agent Job? If so, does the account it runs under have permissions on that path? How are you getting the file list?The S: is a local drive. I ran both of these manually. I have not yet set up the job to run from SQL Agent. I am getting the file list as this:
declare @files table (ID int IDENTITY, FileName varchar(100))
DECLARE @id_hold nvarchar(250),
@id_max nvarchar(250),
@file_names nvarchar(2000),
@file_dir nvarchar(250),
@first_file nvarchar(250)select @file_dir = 'S:\Reports\'
insert into @files execute xp_cmdshell 'dir S:\Reports /b'
insert into [dbo].[SUM_MAIL_REPORTS]
([FILE_ID],[FILE_NAME],[CRDate])
select ID, FileName ,getdate() from @filesdelete [dbo].[SUM_MAIL_REPORTS]
WHERE FILE_NAME = 'Backups'
OR FILE_NAME is nullselect * from [dbo].[SUM_MAIL_REPORTS]
Select @id_hold = min(FILE_NAME), @id_max = max(FILE_NAME)
from [dbo].[SUM_MAIL_REPORTS]
WHERE CAST(CRDate AS DATE) > CAST((GETDATE()-2) AS DATE)select @first_file = 'YES'
DECLARE db_cursor CURSOR FOR
SELECT FILE_NAME
FROM [MonitorDb].[dbo].[SUM_MAIL_REPORTS]
WHERE CAST(CRDate AS DATE) > CAST((GETDATE()-2) AS DATE)
ORDER BY FILE_NAMEOPEN db_cursor
FETCH NEXT FROM db_cursor INTO @id_holdWHILE @@FETCH_STATUS = 0
BEGIN
IF @first_file = 'YES'
BEGIN
select @file_names = ''''+@file_dir+@id_hold
SELECT @first_file='NO'
END
ELSE
select @file_names = @file_names + ';'+@file_dir+@id_hold
select @file_names
FETCH NEXT FROM db_cursor INTO @id_hold
END
-- finish the stringCLOSE db_cursor
DEALLOCATE db_cursorselect @file_names = @file_names + ''''
--select @file_names
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'DBMailProfile'
, @recipients = 'lyle.nielsen@hsc.utah.edu'
, @subject = 'test attachment'
, @body = 'An attachment'
, @file_attachments=@file_namesselect @file_names
Would something like this work for you? It would be a whole lot simpler to maintain and troubleshoot.
DECLARE @files TABLE (
ID Integer IDENTITY,
Filename Varchar(100));DECLARE @file_names Varchar(MAX) = '';
INSERT INTO @files(Filename)
EXECUTE xp_cmdshell 'dir S:\Reports /b';SELECT @file_names = @file_names + ';S:\Reports\' + Filename
FROM @files
WHERE NOT Filename = 'BACKUP'
AND Filename IS NOT NULL;SELECT @file_names = STUFF(@file_names, 1, 1, '');
The only thing you would have left to do is populate your dbo.SUM_MAIL_REPORTS table.
that works great!!!!! Thank You!!
May 18, 2017 at 1:53 pm
lyle.nielsen 31819 - Thursday, May 18, 2017 9:09 AMEd Wagner - Thursday, May 18, 2017 8:38 AMlyle.nielsen 31819 - Thursday, May 18, 2017 7:24 AMJoe Torre - Wednesday, May 17, 2017 3:19 PMIs S: a mapped drive or a local drive? Is this run as a SQL Agent Job? If so, does the account it runs under have permissions on that path? How are you getting the file list?The S: is a local drive. I ran both of these manually. I have not yet set up the job to run from SQL Agent. I am getting the file list as this:
declare @files table (ID int IDENTITY, FileName varchar(100))
DECLARE @id_hold nvarchar(250),
@id_max nvarchar(250),
@file_names nvarchar(2000),
@file_dir nvarchar(250),
@first_file nvarchar(250)select @file_dir = 'S:\Reports\'
insert into @files execute xp_cmdshell 'dir S:\Reports /b'
insert into [dbo].[SUM_MAIL_REPORTS]
([FILE_ID],[FILE_NAME],[CRDate])
select ID, FileName ,getdate() from @filesdelete [dbo].[SUM_MAIL_REPORTS]
WHERE FILE_NAME = 'Backups'
OR FILE_NAME is nullselect * from [dbo].[SUM_MAIL_REPORTS]
Select @id_hold = min(FILE_NAME), @id_max = max(FILE_NAME)
from [dbo].[SUM_MAIL_REPORTS]
WHERE CAST(CRDate AS DATE) > CAST((GETDATE()-2) AS DATE)select @first_file = 'YES'
DECLARE db_cursor CURSOR FOR
SELECT FILE_NAME
FROM [MonitorDb].[dbo].[SUM_MAIL_REPORTS]
WHERE CAST(CRDate AS DATE) > CAST((GETDATE()-2) AS DATE)
ORDER BY FILE_NAMEOPEN db_cursor
FETCH NEXT FROM db_cursor INTO @id_holdWHILE @@FETCH_STATUS = 0
BEGIN
IF @first_file = 'YES'
BEGIN
select @file_names = ''''+@file_dir+@id_hold
SELECT @first_file='NO'
END
ELSE
select @file_names = @file_names + ';'+@file_dir+@id_hold
select @file_names
FETCH NEXT FROM db_cursor INTO @id_hold
END
-- finish the stringCLOSE db_cursor
DEALLOCATE db_cursorselect @file_names = @file_names + ''''
--select @file_names
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'DBMailProfile'
, @recipients = 'lyle.nielsen@hsc.utah.edu'
, @subject = 'test attachment'
, @body = 'An attachment'
, @file_attachments=@file_namesselect @file_names
Would something like this work for you? It would be a whole lot simpler to maintain and troubleshoot.
DECLARE @files TABLE (
ID Integer IDENTITY,
Filename Varchar(100));DECLARE @file_names Varchar(MAX) = '';
INSERT INTO @files(Filename)
EXECUTE xp_cmdshell 'dir S:\Reports /b';SELECT @file_names = @file_names + ';S:\Reports\' + Filename
FROM @files
WHERE NOT Filename = 'BACKUP'
AND Filename IS NOT NULL;SELECT @file_names = STUFF(@file_names, 1, 1, '');
The only thing you would have left to do is populate your dbo.SUM_MAIL_REPORTS table.
that works great!!!!! Thank You!!
You're most welcome. Thanks for the feedback.
Shifting back to your original problem for a moment, does the statement work now? If not, did you check the file system permissions?
Viewing 7 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply