Comment réparer la procédure d'erreur attend le paramètre '@parameters' de type 'ntext / nchar / nvarchar'?

J'essaie d'utiliser une procédure stockée pour afficher les résultats d'une table et une table associée ou des modifications récentes à la database. La procédure stockée est:

set ANSI_NULLS ON set NOCOUNT ON set QUOTED_IDENTIFIER ON go ALTER PROCEDURE [dbo].[MKTG_Current]( @added smalldatetime OUTPUT, @named varchar(50) OUTPUT) AS DECLARE @pDate smalldatetime; DECLARE @AIID int; DECLARE @Table varchar(50); DECLARE @Bork nvarchar(350); SET @pDate = GETDATE() SELECT @Table=[Table], @AIID=AIID, @added=date_added FROM MKTG_Recent WHERE date_added > DATEDIFF(day, date_added, DATEADD(DD, 30, @pDate)) SET @named = @Table SET @Bork = 'SELECT * FROM ' + QUOTENAME(@Table) + ' WHERE AIID= ' + cast(@AIID as varchar(100)) EXECUTE sp_executesql @Bork, @added OUTPUT, @named OUTPUT SELECT @added, @named 

Il est supposé returnner aux éléments en plus des résultats de l'instruction select. Il n'y a pas d'inputs dans la procédure stockée. La procédure stockée comstack correctement dans SQL Management Studio (2008), mais la page renvoie une erreur: Fournisseur Microsoft OLE DB pour l'erreur SQL Server '80040e14'

La procédure attend le paramètre '@parameters' de type 'ntext / nchar / nvarchar'. index.asp, ligne 61

La ligne 61 de la page est en gras:

  dim Objrs, cmd set Objrs = Server.CreateObject("ADODB.RecordSet") set cmd = Server.CreateObject("ADODB.Command") set conn = Server.CreateObject("ADODB.Connection") conn.Open strConnect set cmd.ActiveConnection = conn cmd.CommandText="MKTG_Current" cmd.CommandType=adCmdStoredProc cmd.Parameters.Append cmd.CreateParameter("@added", 135, 2) cmd.Parameters.Append cmd.CreateParameter("@named", 200, 2, 50) Line 61 **set Objrs = cmd.Execute** name_of_table = cmd.Parameters("@named") added = cmd.Parameters("@added") 

J'ai l'printing que cela est dû à une erreur de code SQL, mais je ne le vois pas. Une vérification rapide du Objrs.state renvoie un 0, ce qui signifie que le problème réside définitivement dans le code SQL. Pour la vie de moi, je ne peux pas identifier pourquoi cette erreur est générée.

    Dans cette réponse, je vais essayer de recréer le problème que vous avez mentionné dans la question et je vais aussi expliquer comment j'ai résolu cela.

    Tout d'abord, créons deux tables nommées dbo.MKTG_Recent et dbo.Table_1 utilisant les scripts sous la section Créer un script de tables . J'ai créé ces tables en fonction de certaines hypothèses que j'ai faites en utilisant datatables fournies dans la question. En utilisant le script, la table dbo.MKTG_Recent sera remplie avec 1 logging.

    Ensuite, créez la procédure stockée nommée dbo.MKTG_Current à l'aide du script fourni dans la section Créer un script de procédure stockée .

    Si, nous essayons d'exécuter la procédure stockée avec la command EXEC comme EXEC MKTG_Current null, null , le message d'erreur Msg 214, Level 16, State 3, Procedure sp_executesql, Line 1 Procedure expects parameter '@parameters' of type 'ntext/nchar/nvarchar'. sera jeté. Reorder la capture d'écran # 1

    Après avoir lu MSDN à propos de l'utilisation de la procédure sp_executesql , j'ai trouvé que le second paramètre de la procédure stockée définit les types de parameters de sortie et qu'il doit être une string Unicode. Donc, j'ai modifié la procédure stockée en fournissant le deuxième paramètre en tant que string Unicode en préfixant avec N. Reportez-vous à la capture d'écran n ° 2 pour le changement de procédure stockée.

    Capture d'écran # 3 montre la sortie de la procédure stockée dbo.MKTG_Current après avoir apporté les modifications. La procédure stockée produira deux sorties. Un pour l'instruction de requête dans la variable @Bork qui est passée à sp_executesql et l'autre sortie correspond à l'instruction SELECT qui affiche les variables OUTPUT.

    Basé sur l'exigence, je ne suis pas sûr si vous avez même besoin d'appeler sp_executesql, vous pouvez écrire la procédure stockée comme indiqué dans la section procédure stockée simplifiée . Je peux me tromper parce que je ne comprends pas complètement l'exigence. La capture d'écran n ° 4 montre la sortie de la procédure stockée simplifiée. L'instruction SELECT n'est pas requirejse car les valeurs sont transmises via les parameters OUTPUT . J'ai inclus l' instruction SELECT uniquement pour afficher la sortie de la requête.

    J'espère que cela vous indique la bonne direction.

    Créer un script de tables:

     CREATE TABLE [dbo].[MKTG_Recent]( [Table] [varchar](40) NOT NULL, [AIID] [int] NOT NULL, [date_added] [datetime] NOT NULL ) ON [PRIMARY] GO CREATE TABLE [dbo].[Table_1]( [AIID] [int] NOT NULL, [added] [smalldatetime] NOT NULL, [named] [varchar](50) NOT NULL ) ON [PRIMARY] GO INSERT INTO dbo.MKTG_Recent ([Table], AIID, date_added) VALUES ('Table_1', 1, '2011-08-01') GO 

    Créer un script de procédure stockée:

     SET ANSI_NULLS ON SET NOCOUNT ON SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[MKTG_Current] ( @added SMALLDATETIME OUTPUT , @named VARCHAR(50) OUTPUT ) AS DECLARE @pDate SMALLDATETIME; DECLARE @AIID INT; DECLARE @Table VARCHAR(50); DECLARE @Bork NVARCHAR(350); SET @pDate = GETDATE() SELECT @Table = [Table] , @AIID = AIID , @added = date_added FROM dbo.MKTG_Recent WHERE date_added > DATEDIFF(day, date_added, DATEADD(DD, 30, @pDate)) SET @named = @Table SET @Bork = ' SELECT * FROM ' + QUOTENAME(@Table) + ' WHERE AIID= ' + CAST(@AIID AS VARCHAR(100)) EXECUTE sp_executesql @Bork , @added OUTPUT , @named OUTPUT SELECT @added , @named GO 

    Procédure stockée simplifiée:

     SET ANSI_NULLS ON SET NOCOUNT ON SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[MKTG_Current] ( @added SMALLDATETIME OUTPUT , @named VARCHAR(50) OUTPUT ) AS DECLARE @Table VARCHAR(50); SELECT @named = [Table] , @added = date_added FROM dbo.MKTG_Recent WHERE date_added > DATEDIFF(day, date_added, DATEADD(DD, 30, GETDATE())) SELECT @added AS added , @named AS named GO 

    Captures d'écran:

    # 1: Exécution montrant le message d'erreur

    Message d'erreur

    # 2: Modification apscope à la procédure stockée

    Modified_SP

    # 3: sortie de procédure stockée après les changements

    Stored_procedure_output

    # 4: Sortie de procédure stockée simplifiée

    Simplified_stored_procedure_output

    Vous avez déclaré @Bork en tant que NVARCHAR . Alors pourquoi dites-vous:

     SET @Bork = 'SELECT ...'; 

    ? Devrait être:

     SET @Bork = N'SELECT ...'; 

    C'est ainsi que nous définissons les NVARCHAR (Unicode). Le N signifie national. Si vous sp_executesql ce préfixe N, sp_executesql suppose qu'il s'agit de VARCHAR , ce qui conduit à l'erreur.

    EDIT pour Kieren

    Bien que techniquement oui, vous pouvez déclarer des littéraux NVARCHAR sans le préfixe N, il y a plusieurs raisons pour lesquelles vous ne devriez jamais le faire. L'une consiste à éviter l'erreur que reçoit l'user 873479. D'autres doivent assurer des résultats corrects. Quelques exemples:

    (A) Essayons sp_executesql avec le préfixe N et sans. Même s'il n'y a pas de caractères Unicode dans la string, oublier de mettre le préfixe N lors de l'appel de sp_executesql conduit sp_executesql à la même erreur:

     EXEC sp_executesql N'SELECT 1'; EXEC sp_executesql 'SELECT 1'; 

    Résultats

     ==== 1 ==== Msg 214, Level 16, State 2, Procedure sp_executesql, Line 1 Procedure expects parameter '@statement' of type 'ntext/nchar/nvarchar'. 

    (B) Essayons maintenant une affectation très simple d'un caractère Unicode à une variable NVARCHAR . Remarquez comment, sans le préfixe N, la valeur réelle est perdue?

     DECLARE @x NVARCHAR(32) = 'Ǝ'; SELECT @x; SET @x = N'Ǝ'; SELECT @x; 

    Résultats

     ==== ? ==== Ǝ 

    (C) Maintenant, allons un peu plus loin. Mettons quelques données Unicode dans une table:

     DECLARE @foo TABLE(bar NVARCHAR(1)); INSERT @foo(bar) SELECT N'Ǝ'; -- now someone comes along looking for the row, without using N: SELECT COUNT(*) FROM @foo WHERE bar = 'Ǝ'; 

    Résultats

     ==== 0 

    Et je pourrais find d'autres exemples où la commutation implicite entre CHAR / VARCHAR et NCHAR / NVARCHAR peut transformer les searchs en parsings, mais je pense que les messages d'erreur et les résultats incorrects devraient être suffisants pour le moment.

    Bien sûr, vous pouvez vous en sortir en déclarant des littéraux NVARCHAR sans utiliser le préfixe N, mais seulement si vous NVARCHAR pas de procédures qui attendent NVARCHAR , et seulement si vos données n'incluent pas réellement de caractères Unicode (auquel cas j'aurais se requestr pourquoi vous avez pris la peine d'utiliser NVARCHAR en premier lieu).