在不使用动态 SQL 的情况下更新从文件系统获取文件的二进制字段
Updating a binary field taking a file from filesystem without using dynamic SQL
场景
我在 Sql Server 2005 中有一个 table(我们称之为 myTable
),其中包含一些列,包括一个 varbinary(max)
字段:
- REPORT_ID
int
(主键)
- REPORT_FILE
varbinary(max)
- ...
我经常需要通过 TSQL 脚本从文件系统读取文件来更新包含在 varbinary(max)
列中的文件。这些脚本在 Sql Server Management Studio 中执行。
我编写了以下脚本来使用 OPENROWSET
更新二进制值:
begin try
begin tran
update myOtherTable set field1 = 'value1'
--other instructions
--...
UPDATE myTable
SET [REPORT_FILE] = (SELECT * FROM OPENROWSET(BULK 'c:\filename.ext', SINGLE_BLOB) AS T)
WHERE REPORT_ID = ...
end try
begin catch
if @@TRANCOUNT > 0 begin
rollback tran
--other instructions for error handling
--...
end
end catch
if @@TRANCOUNT > 0 begin
commit tran
end
问题
我想处理文件丢失或者文件名错误的情况;期望的行为是:
rollback
如果出现错误
commit
如果一切正常
如果输入文件丢失,上述脚本会产生错误,但 CATCH
块无法捕获异常,因此交易和对 myOtherTable
的更新仍处于挂起状态,因为 COMMIT
指令未执行。结果我不得不手动回滚事务。
我的解决方案
我发现捕获 CATCH
块中的错误的唯一方法是使用动态 TSQL,所以我的实际脚本是:
declare @dSQL nvarchar(max)
begin try
begin tran
update myOtherTable set field1 = 'value1'
--other instructions
--...
set @dSQL = '
UPDATE myTable
SET [REPORT_FILE] = (SELECT * FROM OPENROWSET(BULK ''c:\filename.ext'', SINGLE_BLOB) AS T)
WHERE REPORT_ID = ...
'
exec sp_executesql @dSQL
end try
begin catch
if @@TRANCOUNT > 0 begin
rollback tran
--other instructions for error handling
--...
end
end catch
if @@TRANCOUNT > 0 begin
commit tran
end
问题
是否可以在不使用动态 TSQL 的情况下实现所需的行为?
最好先检查文件是否存在。
DECLARE @isExists INT;
EXEC master.dbo.xp_fileexist 'C:\filename.ext', @isExists OUTPUT
--If the file exists, then
IF(@isExists = 1)
BEGIN
SELECT 'It exists!'
--Do your work here
END
ELSE
BEGIN
--Return some kind of error message
SELECT 'File does not exist.'
END
场景
我在 Sql Server 2005 中有一个 table(我们称之为 myTable
),其中包含一些列,包括一个 varbinary(max)
字段:
- REPORT_ID
int
(主键) - REPORT_FILE
varbinary(max)
- ...
我经常需要通过 TSQL 脚本从文件系统读取文件来更新包含在 varbinary(max)
列中的文件。这些脚本在 Sql Server Management Studio 中执行。
我编写了以下脚本来使用 OPENROWSET
更新二进制值:
begin try
begin tran
update myOtherTable set field1 = 'value1'
--other instructions
--...
UPDATE myTable
SET [REPORT_FILE] = (SELECT * FROM OPENROWSET(BULK 'c:\filename.ext', SINGLE_BLOB) AS T)
WHERE REPORT_ID = ...
end try
begin catch
if @@TRANCOUNT > 0 begin
rollback tran
--other instructions for error handling
--...
end
end catch
if @@TRANCOUNT > 0 begin
commit tran
end
问题
我想处理文件丢失或者文件名错误的情况;期望的行为是:
rollback
如果出现错误commit
如果一切正常
如果输入文件丢失,上述脚本会产生错误,但 CATCH
块无法捕获异常,因此交易和对 myOtherTable
的更新仍处于挂起状态,因为 COMMIT
指令未执行。结果我不得不手动回滚事务。
我的解决方案
我发现捕获 CATCH
块中的错误的唯一方法是使用动态 TSQL,所以我的实际脚本是:
declare @dSQL nvarchar(max)
begin try
begin tran
update myOtherTable set field1 = 'value1'
--other instructions
--...
set @dSQL = '
UPDATE myTable
SET [REPORT_FILE] = (SELECT * FROM OPENROWSET(BULK ''c:\filename.ext'', SINGLE_BLOB) AS T)
WHERE REPORT_ID = ...
'
exec sp_executesql @dSQL
end try
begin catch
if @@TRANCOUNT > 0 begin
rollback tran
--other instructions for error handling
--...
end
end catch
if @@TRANCOUNT > 0 begin
commit tran
end
问题
是否可以在不使用动态 TSQL 的情况下实现所需的行为?
最好先检查文件是否存在。
DECLARE @isExists INT;
EXEC master.dbo.xp_fileexist 'C:\filename.ext', @isExists OUTPUT
--If the file exists, then
IF(@isExists = 1)
BEGIN
SELECT 'It exists!'
--Do your work here
END
ELSE
BEGIN
--Return some kind of error message
SELECT 'File does not exist.'
END