SQL 从 PHP 执行时服务器查询不起作用

SQL Server Query not working when executed from PHP

我在 SQL Server 中的 table 中有一组 triggers,当我在 SQL Server Management Studio 中执行查询时,它们工作正常。但是当它们从我的 php 文件中执行时,它们不会生效。我使用 SQL Server Profiler 并且触发器到达执行的最后一行,即在我的日志 table 中插入,但在此之后我得到一个 Attention 错误。这是我删除语句的触发器:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- Batch submitted through debugger: SQLQuery25.sql|7|0|C:\Users\ADMINI~1\AppData\Local\Temp\~vsB4EE.sql

ALTER TRIGGER [dbo].[OperationStructureFields_delete]
ON [dbo].[OperationStructureFields]
FOR DELETE
AS
BEGIN
    DECLARE
        @id INT,
        @result varchar(MAX),
        @user varchar(MAX),
        @LoopCounter INT = 1, 
        @MAX INT, 
        @Column NVARCHAR(100),
        @Type NVARCHAR(100),
        @Value NVARCHAR(100),
        @ValueXML xml,
        @Sql NVARCHAR(MAX),
        @Tmp NVARCHAR(MAX),
        @LoopCounter2 INT = 1,
        @MAX2 INT,
        @Message nvarchar(2048)
    SELECT @user = system_user
    SELECT @MAX = MAX(ORDINAL_POSITION) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'OperationStructureFields'
    SELECT @MAX2 = MAX(ID) FROM deleted
    SELECT @LoopCounter2 = MIN(ID) FROM deleted
    Select * into #deleted from deleted
    WHILE(@LoopCounter2 <= @MAX2)
    BEGIN
        SET @LoopCounter = 1
        SET @result = '{'
        WHILE(@LoopCounter <= @MAX)
        BEGIN
           SELECT @Column = COLUMN_NAME, @Type = DATA_TYPE
           FROM INFORMATION_SCHEMA.COLUMNS WHERE ORDINAL_POSITION = @LoopCounter and TABLE_NAME = 'OperationStructureFields'
           if (@Type = 'xml')
           BEGIN
            SET @Sql = 'SELECT @ValueXML = ' + @Column + ' FROM #deleted where ID=' + CONVERT(varchar(200),@LoopCounter2,0)
            exec sp_executesql @Sql, N'@ValueXML xml out', @ValueXML out
            SET @Value = CONVERT(VARCHAR(MAX),@ValueXML,0)
           END
           ELSE
           BEGIN
             SET @Sql = 'SELECT @Value = ' + @Column + ' FROM #deleted where ID=' + CONVERT(varchar(200),@LoopCounter2,0)
             exec sp_executesql @Sql, N'@Value varchar(MAX) out', @Value out 
           END    
           IF (@Value is not null or @Value != '') and  (@Type = 'datetime2' or @Type = 'datetime' or @Type = 'date')
           BEGIN
                IF @result = '{'
                BEGIN
                    SET @result = @result + ' "' + @Column + '":"' + CONVERT(VARCHAR(20),@Value,120) + '"'
                END
                ELSE
                BEGIN
                    SET @result = @result + ', "' + @Column + '":"' + CONVERT(VARCHAR(20),@Value,120) + '"'
                END
           END
           ELSE IF (@Value is not null or @Value != '')
           BEGIN
                IF @result = '{'
                BEGIN
                    SET @result = @result + ' "' + @Column + '":"' + @Value + '"'
                END
                ELSE
                BEGIN
                    SET @result = @result + ', "' + @Column + '":"' + @Value + '"'
                END
           END
           SET @LoopCounter  = @LoopCounter + 1 
        END
        SET @result = @result + '}'
        INSERT INTO sys_logs (username,datahora,tabela,[object_id],[action],oldvalue) values (@user,GETDATE(),'OperationStructureFields',@LoopCounter2,'DELETE',@result)
        delete from #deleted where ID = @LoopCounter2
        select @LoopCounter2 = MIN(ID) from #deleted where ID > @LoopCounter2  
    END
END

以及我的 SQL Server Profiler 的打印件:

PHP代码是:

$res = sqlsrv_query($connection, $_sql, array(), array('Scrollable' => 'buffered'));

并且变量 $_sql 具有以下值:

DELETE FROM OperationStructureFields WHERE ID= '66817'

它不会 return 任何错误。

PHP 版本为 5.5.16

我在 php 文件中执行了 SELECT @@OPTIONS 并获得了以下选项:

ANSI_WARNINGS
ANSI_PADDING
ANSI_NULLS
QUOTED_IDENTIFIER
ANSI_NULL_DFLT_ON
CONCAT_NULL_YIELDS_NULL

与 SQL Server Management Studio 的唯一区别是选项 ARITHABORT,即 SQL Server Management Studio 中的 ON

您知道是什么原因造成的吗?

更新:

我相信这可能与我的 PHP 设置有关。在我的 phpinfo() 中,我为 sqlsrv 设置了以下设置:

同样在 SQL Server Profiler 我在 Audit Login 中有以下定义:

-- network protocol: LPC
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed

每个应用程序 SQL 驱动程序(包括 SSMS)都有标准的 SET 选项。这些可以被覆盖,但默认情况下,驱动程序将传递某些设置值。 (如果您不知道我在说什么,请查看 this article 以了解选项是什么,并了解如何确定正在使用的选项。

我的建议是确定您的应用程序正在使用哪些 SET 选项,然后模仿 SSMS 中的选项,然后从那里进行故障排除。您的另一个选择是继续并从您的应用程序执行设置语句以与 SSMS 的默认设置保持一致。几年前,我们在 Node.js 应用程序中做了类似的事情,因为我们收到了一些从 .Net 中 运行 正常的过程返回的错误。一旦我们将 Node 中的语句添加到 parrot .Net 中,一切正常。

我不确定您的问题是由于 SET 选项引起的,但我认为这很有可能。

消息

Changed database context to XXXXXXX

Changed language setting to YYYYYYY

不是错误信息。它们是信息性消息,应被应用程序忽略。 PHP 可以配置为忽略它。

严重级别:https://msdn.microsoft.com/en-us/library/ms164086.aspx

PHP 设置:

1) php.ini 变化:

mssql.min_error_severity = 11
mssql.min_message_severity = 11

2) 通过执行

mssql_min_error_severity(11);

就在执行 mssql_query()

之前

http://php.net/manual/en/function.mssql-min-error-severity.php

更新:

3) 触发器应该有

set nocount on;

在代码的顶部,就在:

之后
AS
BEGIN

这将阻止向应用程序发送多条信息性消息(如 "xx rows affected")。