J'ai un set de sortingggers
dans ma table dans SQL Server
et lorsque j'exécute les requêtes dans SQL Server Management Studio
ils fonctionnent correctement. Mais quand ils sont exécutés à partir de mes files php
, ils ne prennent pas effet. J'ai utilisé SQL Server Profiler
et le triggersur arrive à la dernière ligne d'exécution qui est l'insertion dans ma table de journal, mais après cela, je reçois une erreur Attention
. Voici mon triggersur pour une instruction delete:
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\3\~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
Et une printing de mon profileur SQL Server:
Le code PHP est:
$res = sqlsrv_query($connection, $_sql, array(), array('Scrollable' => 'buffered'));
et la variable $_sql
a la valeur suivante:
DELETE FROM OperationStructureFields WHERE ID= '66817'
Et il ne renvoie aucune erreur.
La version PHP est 5.5.16
.
J'ai exécuté SELECT @@OPTIONS
dans mon file php et j'ai obtenu les options suivantes:
ANSI_WARNINGS ANSI_PADDING ANSI_NULLS QUOTED_IDENTIFIER ANSI_NULL_DFLT_ON CONCAT_NULL_YIELDS_NULL
La seule différence avec SQL Server Management Studio est l'option ARITHABORT
ON
dans SQL Server Management Studio.
Avez-vous des idées sur ce qui pourrait en être la cause?
MISES À JOUR:
Je crois que cela peut être quelque chose sur mes parameters PHP. Dans mon phpinfo()
j'ai les parameters suivants pour sqlsrv
:
Aussi dans SQL Server Profiler
j'ai les définitions suivantes dans 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
messages
Context de database modifié en XXXXXXX
Modification du paramètre de langue sur YYYYYYY
ne sont pas des messages d'erreur. Ce sont des messages d'information et devraient être ignorés par les applications. PHP peut être configuré pour l'ignorer.
Niveaux de gravité: https://msdn.microsoft.com/fr-fr/library/ms164086.aspx
Paramètres PHP:
1) changements de php.ini:
mssql.min_error_severity = 11 mssql.min_message_severity = 11
ou
2) en exécutant
mssql_min_error_severity(11);
juste avant l'exécution de mssql_query ()
http://php.net/manual/fr/function.mssql-min-error-severity.php
METTRE À JOUR:
3) Le triggersur devrait avoir
set nocount on;
en haut du code, juste après:
AS BEGIN
Cela empêchera l'envoi de plusieurs messages d'information (comme "xx rows affected") à l'application.
Chacun des pilotes SQL d'application (y compris SSMS) dispose d'options SET standard. Ceux-ci peuvent être remplacés, mais par défaut, le pilote va passer certaines valeurs de réglage. (Si vous ne savez pas de quoi je parle, jetez un oeil à cet article pour avoir une idée de ce que sont les options et pour savoir comment déterminer quelles options sont utilisées.
Ce que je suggérerais serait de déterminer quelles sont les options SET que votre application utilise, puis de les imiter dans SSMS, puis de résoudre les problèmes à partir de là. Votre autre option serait d'aller de l'avant et d'exécuter des instructions set à partir de votre application pour être cohérent avec les parameters par défaut de SSMS. Nous avons fait quelque chose de similaire à cela dans une application Node.js quelques années parce que nous recevions un certain nombre d'erreurs renvoyées par procs qui fonctionnaient bien dans .Net. Une fois que nous avons ajouté des déclarations dans le nœud pour perroquet .Net tout a bien fonctionné.
Je ne suis pas certain que votre problème est dû à SET Options, mais je pense que c'est probable.