Sql 如何修复错误过程期望参数'@参数';类型为';ntext/nchar/nvarchar';?

Sql 如何修复错误过程期望参数'@参数';类型为';ntext/nchar/nvarchar';?,sql,sql-server,stored-procedures,asp-classic,Sql,Sql Server,Stored Procedures,Asp Classic,我正在尝试使用存储过程来显示表的结果、关联表或数据库最近的更改。存储过程是: 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; D

我正在尝试使用存储过程来显示表的结果、关联表或数据库最近的更改。存储过程是:

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 
除了select语句的结果之外,它还应该返回到项。存储过程没有输入。存储过程在SQL Management Studio(2008)中编译良好,但页面返回错误: SQL Server的Microsoft OLE DB提供程序错误“80040e14”

过程需要类型为“ntext/nchar/nvarchar”的参数“@parameters”。 index.asp,第61行

本页第61行为粗体:

  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")  

我的印象是这是由SQL代码错误引起的,但我没有看到它。对Objrs.state的快速检查返回0,这意味着问题肯定出在SQL代码中。就我个人而言,我无法确定产生此错误的原因。

您将@Bork声明为
NVARCHAR
。那你为什么说:

SET @Bork = 'SELECT ...';
??应该是:

SET @Bork = N'SELECT ...';
这就是我们定义
NVARCHAR
(Unicode)字符串的方式。N代表国家。如果省略该N前缀,
sp_executesql
假定它是
VARCHAR
,这将导致错误

编辑Kieren的

虽然从技术上讲是的,但您可以声明不带N前缀的
NVARCHAR
文本,但有几个原因说明您不应该这样做。一个是避免user873479接收到的错误。另一些是为了确保正确的结果。一些例子:

(A) 让我们尝试使用带有N前缀和不带前缀的sp_executesql。即使字符串中没有实际的Unicode字符,调用
sp_executesql
时忘记输入N前缀也会导致与此问题完全相同的错误:

EXEC sp_executesql N'SELECT 1';
EXEC sp_executesql 'SELECT 1';
结果

====
1
====
Msg 214, Level 16, State 2, Procedure sp_executesql, Line 1
Procedure expects parameter '@statement' of type 'ntext/nchar/nvarchar'.
====
?
====
Ǝ
====
0
(B) 现在,让我们尝试一个非常简单的Unicode字符赋值给
NVARCHAR
变量。注意,如果没有N前缀,实际值是如何丢失的

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

====
1
====
Msg 214, Level 16, State 2, Procedure sp_executesql, Line 1
Procedure expects parameter '@statement' of type 'ntext/nchar/nvarchar'.
====
?
====
Ǝ
====
0
(C) 现在让我们更进一步。让我们将一些Unicode数据放入表中:

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 = 'Ǝ';
结果

====
1
====
Msg 214, Level 16, State 2, Procedure sp_executesql, Line 1
Procedure expects parameter '@statement' of type 'ntext/nchar/nvarchar'.
====
?
====
Ǝ
====
0
我还可以举更多的例子,在CHAR/VARCHAR和NCHAR/NVARCHAR之间进行隐式切换可以将搜索转化为扫描,但我认为错误消息和错误结果现在应该足够了


因此,当然,您可以不使用N前缀而声明
NVARCHAR
文本,但前提是您没有调用预期
NVARCHAR
的过程,并且数据实际上不包含任何Unicode字符(在这种情况下,我想知道为什么您首先要费心使用
NVARCHAR

在这个答案中,我将尝试重现您在问题中提到的问题,并解释我是如何解决的

首先,让我们使用创建表脚本部分下的脚本创建两个名为
dbo.MKTG_-Recent
dbo.Table_1
的表。我基于使用问题中提供的数据所做的一些假设创建了这些表。使用该脚本,表
dbo.MKTG_-Recent
将填充为H1记录

接下来,使用创建存储过程脚本部分提供的脚本创建名为
dbo.MKTG_Current
的存储过程

如果我们尝试使用EXEC命令执行存储过程,将其设置为
EXEC MKTG_Current null,null
,则错误消息
Msg 214,级别16,状态3,过程sp_executesql,第1行
过程需要类型为“ntext/nchar/nvarchar”的参数“@parameters”。
将被抛出。请参阅屏幕截图#1

在通读了有关该过程的用法后,我发现存储过程的第二个参数定义了输出参数的类型,它必须是Unicode字符串。因此,我修改了存储过程,将第二个参数作为Unicode字符串,并在前面加上N。有关第二个参数的详细信息,请参阅屏幕截图#2e存储过程更改

屏幕截图#3显示了进行更改后存储过程的输出
dbo.MKTG_Current
。存储过程将产生两个输出。一个输出用于传递给sp_executesql的变量@Bork中的查询语句,另一个输出对应于显示输出v的SELECT语句变量

基于此需求,我不确定您是否需要调用sp_executesql,您可以按照简化存储过程部分所示编写存储过程。我可能错了,因为我不完全理解此需求。屏幕截图#4显示简化存储过程的输出。选择Statementt不是必需的,因为值是通过输出参数传递的。我包含SELECT语句只是为了显示查询输出

希望这能为你指明正确的方向

创建表脚本:

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
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    
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
创建存储过程脚本:

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
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    
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
简化存储过程:

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
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    
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
屏幕截图:

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
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    
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
#1:显示错误消息的执行

#2:对存储过程所做的更改

#3:更改后的存储过程输出

#4:简化存储过程输出


检查您是否有相同的SP,但有另一个参数列表(请参阅dbo架构中的not)另一条评论-如果在您的WHERE子句时间范围内MKTG_最近更新了多个表,您知道您将得到哪一个表吗?我当然不知道。这不是真的,您可以使用不带N的文本,只要使用NVARCHAR typesOkay@Kieren就可以了,您尝试过调用
EXEC sp_executesql'SELECT 1';
?您有更好的answ吗er as t