Partager via


MSSQLSERVER_4186

Détails

Nom du produit SQL Server
ID de l’événement 4186
Source de l’événement MSSQLSERVER
Composant SQLEngine
Nom symbolique
Texte du message Colonne '%ls.%.*ls' ne peut pas être référencé dans la clause OUTPUT, car la définition de colonne contient une sous-requête ou fait référence à une fonction qui effectue l’accès aux données utilisateur ou système. Une fonction est supposée par défaut pour effectuer l’accès aux données s’il n’est pas lié au schéma. Envisagez de supprimer la sous-requête ou la fonction de la définition de colonne ou de supprimer la colonne de la clause OUTPUT.

Explication

Pour empêcher un comportement non déterministe, la clause OUTPUT ne peut pas référencer une colonne provenant d'une vue ou d'une fonction retournant une table en ligne lorsque cette colonne est définie par l'une des méthodes suivantes :

  • Sous-requête.

  • Fonction définie par l’utilisateur qui effectue un accès aux données utilisateur ou système, ou qui est supposée effectuer ce type d’accès.

  • Dans sa définition, une colonne calculée qui contient une fonction définie par l’utilisateur effectue l’accès aux données utilisateur ou système.

Exemples

Afficher la colonne définie par une sous-requête

L’exemple suivant crée une vue qui utilise une sous-requête dans la liste de sélection pour définir la colonne State. Une instruction UPDATE fait ensuite référence à la colonne State dans la clause OUTPUT et échoue à cause de la sous-requête dans la liste de sélection.

USE AdventureWorks2012;  
GO  
CREATE VIEW dbo.V1  
AS  
    SELECT City,  
-- subquery to return the State name  
           (SELECT Name FROM Person.StateProvince AS sp   
            WHERE sp.StateProvinceID = a.StateProvinceID) AS State  
    FROM Person.Address AS a;  
GO  
--Reference the State column in the OUTPUT clause of an UPDATE statement  
UPDATE dbo.V1   
SET City = City + 'Test'   
OUTPUT deleted.City, deleted.State, inserted.City, inserted.State  
WHERE State = 'Texas';  
GO  

Afficher la colonne définie par une fonction

L’exemple suivant crée une vue qui utilise la fonction scalaire dbo.ufnGetStock pour accéder aux données et définir la colonne CurrentInventory dans la liste de sélection SQL. Une instruction UPDATE fait ensuite référence à la CurrentInventory colonne dans la clause OUTPUT.

USE AdventureWorks2012;  
GO  
CREATE VIEW Production.ReorderLevels  
AS  
    SELECT ProductID, ProductModelID, ReorderPoint,  
           dbo.ufnGetStock(ProductID) AS CurrentInventory  
    FROM Production.Product;  
GO  
  
UPDATE Production.ReorderLevels  
SET ReorderPoint += CurrentInventory  
OUTPUT deleted.ReorderPoint, deleted.CurrentInventory,  
       inserted.ReorderPoint, inserted.CurrentInventory  
WHERE ProductModelID BETWEEN 75 and 80;  

Action de l'utilisateur

L’erreur 4186 peut être corrigée de l’une des manières suivantes :

  • Utilisez des jointures au lieu de sous-requêtes pour définir la colonne dans la vue ou la fonction. Par exemple, vous pouvez réécrire la vue dbo.V1 comme suit.

    USE AdventureWorks2012;  
    GO  
    CREATE VIEW dbo.V1  
    AS  
        SELECT City, sp.Name AS State  
        FROM Person.Address AS a   
        JOIN Person.StateProvince AS sp   
        ON sp.StateProvinceID = a.StateProvinceID;  
    
  • Examinez la définition de la fonction définie par l’utilisateur. Si la fonction n’effectue pas d’accès aux données utilisateur ou système, modifiez la fonction pour inclure la clause WITH SCHEMABINDING.

  • Supprimez la colonne de la clause OUTPUT.

Voir aussi

Output, clause (Transact-SQL)