我创建了用于在'order'表中插入记录的存储过程。我试图从变量Order
中的另一个数据库中获取@Id
表的最大id。
架构如下:
CREATE PROCEDURE order_add
@orderstatus nvarchar(1000),
@paymentstatus nvarchar(1000),
@Customer nvarchar(1000),
@createdon nvarchar(1000),
@ordertotal nvarchar(1000)
AS
DECLARE @Id int;
BEGIN
SELECT MAX(Id)
INTO @Id
FROM [Database2].dbo."Order";
INSERT INTO Customer
VALUES(@Id, @orderstatus, @paymentstatus, @Customer, @createdon, @ordertotal);
END;
当我执行此存储过程时,我收到此错误:
消息102,级别15,状态1,过程order_add,行13 [批处理开始行0] '@Id'附近的语法不正确。
我该怎么做才能解决这个问题?
您的程序具有SELECT
语句的时尚语法:
select @Id = max(Id)
from [Database2].dbo.Order
insert into Customer (id, orderstatus, paymentstatus, Customer, createdon, ordertotal)
values(@Id, @orderstatus, @paymentstatus, @Customer, @createdon, @ordertotal
);
注意 :
insert into
语句时,始终明确限定所有列名称。你有一个“解决”这个问题的答案。但请停下来思考一下你的代码。考虑数据库服务器中对象的层次结构。您在特定数据库中创建过程。使用数据库名称限定表名称是危险的 - 即使该名称与创建过程的名称相同。为什么?因为有人最终会想要创建这个数据库的副本。可能用于测试,灾难恢复等。现在您的过程将失败或无法产生正确的结果。
此外,您需要在代码中获得指导。大概你在一个拥有多个成员的团队中工作,其中至少有一个成员具有丰富的经验。您的小组应该进行代码审查,以提高代码编写的质量,提高组内的业务知识水平,并识别编码错误。这个过程应该抓住很多问题,其中一些我会提到。
您应该使用SET而不是SELECT来分配标量变量。为什么?因为当查询找不到行时,存在细微且显着的差异。在这种情况下,SET将为变量赋值NULL,而SELECT将保持不变。更多here。
您还需要考虑数据类型。使用正确的,不要只是将所有内容定义为字符串 - 尤其是非常大的字符串。我猜你的大多数参数都不应该是nvarchar - 当然不包含1000个字符。
为什么在第一个select语句中使用双引号?如果你遵循对象名称的规则(你应该),你不需要分隔它们(这是双引号的作用)。保持一致并遵守规则。再次 - 不要使用数据库名称限定表名,除非您绝对打算这样做有充分理由。如果您打算这样做,那么请使用同义词。这将使某人的生活更轻松,并给你良好的业力。
最后,始终指定您在insert语句中填充的列的列表。不要 - 重复不 - 养成省略的懒惰习惯。为什么?列的顺序可能会发生变化 - 尽管看起来不太可能。可能会添加一个带有默认值的附加列。假设在这种情况下应使用默认值,您现在必须更改语句。通过指定列列表,您的代码将在添加列后继续正常工作。