使用PHP运行使用SQL Server中存储的过程和事务的查询会导致神秘的错误

使用PHP运行使用SQL Server中存储的过程和事务的查询会导致神秘的错误,php,sql,sql-server,error-handling,transactions,Php,Sql,Sql Server,Error Handling,Transactions,这是最奇怪的事情,我不知道为什么或者发生了什么。在SQL Server中运行一切正常,但在PHP中运行时会导致错误 在PHP中,我构建了一个包含一对多查询或语句的动态语句。看起来是这样的: begin try begin transaction -- statement 1 UPDATE table_name SET status = 1 WHERE things='stuff'; -- dynamic: to run after inserts

这是最奇怪的事情,我不知道为什么或者发生了什么。在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
今天早上,有人来找我,因为所有这些的头版都在向他们抛出错误<代码>警告:mssql_query()[function.mssql query]:消息:回滚事务请求没有相应的BEGIN事务。此代码已几个月未被触及,并且没有任何问题。此后,存储过程中的代码可能已更改

我将代码复制到SQLServerManagementStudio进行测试,通过直接复制和粘贴,一切正常。没有错误,没有警告,只是成功了

接下来,我在线查找事务,并将
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
)
(不过,提醒一下:如果我在SQLServerMgmtStudio中运行完全相同的代码,则不会返回任何错误)

该错误涉及在PHP构建的动态查询中列出的每个
SP_TEST#
过程结束时调用的SP我无法将SP代码复制到此处,因为这是工作资料,我没有编写它们,所以我也不想对它们进行解释,因为它们太大,格式不好。但是,我将显示出现错误的
SP_TEST_记录的顶部(不在第247行):

所以-有一件事我知道。。。我的PHP事务是如何被动态语句调用的某个存储过程中的某个东西结束的,这就是事务问题的原因。这些存储过程中有事务

  • 但是当我运行相同的代码时,为什么在SQL Server中看不到空插入错误?如果有空插入,则有空插入。。。那么,如果它是从PHP调用的,为什么会有不同呢

  • 更不重要的是,一开始我的事务是如何被一个存储过程结束的

  • 为什么当代码在PHP中运行时,而不是在SQL Server中运行时,转换被SP终止

  • 是否存在操作事务层次结构的某些执行并发顺序


    • 我不想直接删除这个问题,因为它至少对我来说是一次很好的学习经历。然而,这是一个非常本地化的问题。我前一阵子就知道答案了,所以我记不起具体的细节

      这肯定是因为在一个被调用的存储过程中发生了一些事情。我很惊讶地发现错误是这样冒出来的,尤其是在PHP中。我猜误差范围在其中起了一定作用。。。PHP接受了它看到的第一个错误,但在SQL server中运行代码使其更容易失败(因此我没有看到错误)。不知道故障排除。。。当有疑问的时候-更深一点,哈哈

      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