最奇怪的事情,我不确定为什么或发生了什么。 一切在SQL Server中运行良好,但在PHP中运行时会导致错误。
在 PHP 中,我构建一个包含一对多查询或语句的动态语句。 它看起来像这样:
begin try
begin transaction
-- statement 1
UPDATE table_name SET status = 1 WHERE things='stuff';
-- dynamic: to run after inserts
exec [dbo].[SP_TEST_2];
exec [dbo].[SP_TEST_3];
exec [dbo].[SP_TEST_9];
exec [dbo].[SP_TEST_14];
commit
select 'successful' as for_php_success_message
end try
begin catch
rollback
select error_number() as for_php_error_number
,error_severity() as for_php_error_severity
,error_state() as for_php_error_state
,error_procedure() as for_php_error_procedure
,error_line() as for_php_error_line
,error_message() as for_php_error_message;
end catch
今天早上,有人来找我,因为所有这些的头版都在向他们抛出错误。 Warning: mssql_query() [function.mssql-query]: message: The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
这段代码几个月来一直没有动过,没有任何问题。 从那时起,存储过程中的代码可能已更改。
我将代码复制到SQL Server Management Studio进行测试,通过直接复制和粘贴,一切运行良好。 没有错误,没有警告,只是成功。
接下来,我在线查找交易并将rollback
更改为if @@trancount>0 rollback
,这确实修复了交易错误; 但是 - 我有一个来自 PHP 的新错误:
Array
(
[for_php_error_number] => 50000
[for_php_error_severity] => 16
[for_php_error_state] => 1
[for_php_error_procedure] => SP_TEST_Record
[for_php_error_line] => 247
[for_php_error_message] => spTEST_Record: 515: Cannot insert the value NULL into column 'TEST_DATA', table 'tempdb.dbo.#IDs________________________________________________________________________________________________________________00000001D27E'; column does not allow nulls. INS
)
(不过,提醒一下:如果我在SQL Server Mgmt Studio中运行确切的代码,则不会返回任何错误(
该错误涉及在 PHP 构建的动态查询中列出的每个SP_TEST_#
过程结束时调用的 SP。 我无法将 SP 代码复制到这里,因为这是工作内容,我没有编写它们,所以我真的不想解释它们,因为它们很大而且格式不好。 但是,我将显示发生错误的SP_TEST_RECORD
顶部(不在第 247 行(:
ALTER PROCEDURE [dbo].[SP_TEST_Record] (
@Test_ID real=0, @debug int=1, @create_entry int=0, @autoclose bit=0, @autodelete bit=0
)
AS
BEGIN
SET NOCOUNT ON;
declare @vtest_id real; set @vtest_id=@Test_ID
declare @vdebug int; set @vdebug=@debug
declare @vcreate_entry bit; set @vcreate_entry=@create_entry
declare @vautoclose bit; set @vautoclose=@autoclose
declare @vautodelete bit; set @vautodelete=@autodelete
declare @test_date datetime; set @test_date=getutcdate()
declare @ct int;
begin try
begin tran
if object_id('tempdb..#IDs') is not null drop table #IDs
CREATE TABLE #IDs (TYC_ID int not null, TYC_TYPE_ID int not null, TYC_ENV_ID int not null, TEST_DATA nvarchar(2000) null) ON [PRIMARY]
ALTER TABLE #IDs ADD PRIMARY KEY NONCLUSTERED (TYC_ID, TYC_TYPE_ID, TYC_ENV_ID)
insert into #IDs(TYC_ID, TYC_TYPE_ID, TYC_ENV_ID, TEST_DATA)
select TYC_ID, TYC_TYPE_ID, TYC_ENV_ID, TEST_DATA from SR_TESTING where TEST_ID=@vTest_ID
所以 - 我知道的一件事...不知何故,我的 PHP 事务被动态语句调用的存储过程中的某个东西结束了,这是事务问题的原因。 这些存储过程中存在事务。
但是,为什么当我运行完全相同的代码时,我在 SQL Server 中看不到空插入错误?如果存在空插入,则存在空插入...那么,如果它是否从 PHP 调用会有所不同呢?
不太重要的是,我的事务在开始时是如何被其中一个存储过程结束的?
为什么当代码在PHP中运行时,事务由SP结束,而在SQL Server中运行时没有?
是否有一些执行-并发-操作顺序-事务层次结构-发生了什么?
我不想直接删除这个问题,因为这至少对我来说是一次很棒的学习经历。 然而,这是一个非常本地化的问题。 我前段时间想出了答案,所以我不记得具体细节了......
这肯定是由于在下行调用的某个存储过程中发生了某些事情。 我很惊讶地发现错误以这种方式冒泡,尤其是对于 PHP。 我想错误范围在其中发挥了作用...PHP 接受了它看到的第一个错误,但在 SQL Server 中运行代码允许它更优雅地失败(所以我没有在那里看到错误(。 邓诺。 故障 排除。。。当有疑问时 - 更深入,哈哈...