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