有没有一种方法可以使SQLServer触发器与雄辩的查询一起使用?

时间:2019-04-30 08:49:21

标签: sql-server laravel-5 eloquent database-trigger

我正在使用Laravel 5.5和SQLServer开发应用程序。我被要求创建一个“历史记录”表,在该表中我们跟踪UPDATE操作。例如,如果更新票证的描述,则会插入该字段的ID,字段,先前值和新值。

通常,这是通过数据库中的触发器完成的,因此我已经设置了after_update触发器。

现在,我的触发器有效,但是用Eloquent编写查询时无效。如果我使用模型使用的相同连接的PDO对象,则触发器将起作用。如果我在数据库界面中使用相同的连接编写查询,则它们将起作用。但是,如果我用Eloquent编写了相同的查询,则字段会更新,但是触发器不会触发。

我知道观察者的存在像触发器一样,我确实将它们设置为执行几乎相同的操作。但是,我不明白为什么触发器不起作用,并且我想知道这是正常现象还是我的设置在某种程度上有问题。

我在database.php文件中的连接如下所示(默认值已在此处删除):

'uti' => [
            'driver'   => 'sqlsrv',
            'host'     => env('DB_HOST'),
            'database' => env('DB_DATABASE'),
            'username' => env('DB_USERNAME'),
            'password' => env('DB_PASSWORD'),
            'prefix'   => '',
            'charset'   => 'iso-8859-1',
            'characterset' => 'iso-8859-1',
            'collation' => 'French_CI_AS',
        ],

与触发器一起工作的代码:

use Illuminate\Support\Facades\DB;

$oPdo = DB::connection('uti')->getPdo();
$sQuery = $oPdo->prepare("
            UPDATE TICKET SET
            T_DESC = :sDesc
            WHERE T_CODE = :iCode");
$sQuery->execute([':sDesc' => $sDesc, ':iCode' => $code]);

无法使用的代码:

$oTicket = Ticket::find($code);
        $oTicket->T_DESC = $sDesc;
        $oTicket->save();

触发器是这样的(表TICKET的每个字段都有更多的'IF UPDATE()'):

USE [DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[after_update_ticket]
ON [dbo].[TICKET] 
AFTER UPDATE
AS
BEGIN -- begin trigger
SET NOCOUNT ON

IF EXISTS (SELECT * FROM INSERTED) And EXISTS(SELECT * FROM DELETED)
-- Is an update --
BEGIN -- begin if update
    DECLARE @user int = 1;
        IF NOT UPDATE (MODIFICATION_DATE) AND NOT UPDATE (MODIFICATION_USER)
            BEGIN -- begin if not update
-- If database connection user is letter + number, user id = number
            IF (ISNUMERIC(SUBSTRING(USER_NAME(USER_ID (CURRENT_USER)),2, LEN(USER_NAME(USER_ID (CURRENT_USER)))))=1)
                BEGIN
                    SET @user = SUBSTRING(USER_NAME(USER_ID (CURRENT_USER)),2, LEN(USER_NAME(USER_ID (CURRENT_USER))));
                END

            -- Update MODIFICATION date and user --

                UPDATE [TICKET] SET 
                MODIFICATION_DATE = CURRENT_TIMESTAMP, 
                MODIFICATION_USER = @user
                WHERE CODE = (SELECT T_CODE FROM inserted)


            -- History trigger --
            IF UPDATE(T_DESC)
                BEGIN
                INSERT INTO HISTORIQUE 
                (H_DATE,H_TABLE,H_FIELD,H_BEFORE,H_AFTER,H_CODE,CREATION_USER,CREATION_DATE) 
                VALUES 
                (CURRENT_TIMESTAMP,'TICKET','T_DESC',(SELECT T_DESC FROM deleted),(SELECT T_DESC FROM inserted),(SELECT T_CODE FROM inserted),@user,CURRENT_TIMESTAMP)
                END
END -- end if no update

END -- end if update

END -- end trigger

我曾尝试研究laravel和eloquent的触发器,但是查看文档和一些stackoverflow问题并没有为我提供有关Eloquent触发器的预期行为的信息。我发现有些人是通过迁移手动创建的,因此我认为它们应该可以工作,但是我找不到帮助我的信息。

谢谢。

更新

Eloquent在字段更新时同时处理created_at和updated_at的自动 updating 方法。 (此处,updated_at定义为MODIFICATION_DATE)。结果,只有一个查询被发送到数据库:

update [TICKET] set [T_DESC] = 'desc with eloquent', [MODIFICATION_DATE] = '2019-05-02 08:45:53' where [T_CODE] = 16770

由于我的IF NOT UPDATE (MODIFICATION_DATE)语句在触发器中,因此阻止了它被触发。

我在票证模型中设置了public $timestamps = false;,以使Laravel不会在updated_at上进行自动更新,并且触发器照常触发。

0 个答案:

没有答案