sql server中@output参数必须显式声明并调用时加output关键字,否则不回传值;mysql用out,postgresql用out参数或returns,三者语法和语义差异显著。

SQL Server 存储过程中 @output 参数必须显式声明为 OUTPUT
不加 OUTPUT 关键字,参数就是输入参数,即使你在调用时传了变量,存储过程内部修改它也不会回传到外部。这是最常踩的坑——看着代码像有输出,实际值根本没变。
声明方式很简单:
CREATE PROCEDURE GetOrderCount
@customerId INT,
@orderCount INT OUTPUT -- 必须写 OUTPUT
AS
BEGIN
SELECT @orderCount = COUNT(*)
FROM Orders
WHERE CustomerID = @customerId;
END
-
OUTPUT是关键字,不是注释,缺一不可 - 调用时也得在变量后补
OUTPUT,否则照样不生效:EXEC GetOrderCount 123, @cnt OUTPUT - 不能对只读对象(比如常量、字面量)用
OUTPUT,会报错:EXEC GetOrderCount 123, 0 OUTPUT❌
MySQL 不支持 OUTPUT 参数,改用 OUT 或用户变量
MySQL 的存储过程参数类型是 IN / OUT / INOUT,没有 OUTPUT 这个词。写成 OUTPUT 会直接语法错误。
正确写法:
DELIMITER $$
CREATE PROCEDURE GetOrderCount(IN p_customer_id INT, OUT p_order_count INT)
BEGIN
SELECT COUNT(*) INTO p_order_count
FROM orders
WHERE customer_id = p_customer_id;
END$$
DELIMITER ;
- 调用时不用额外标记:
CALL GetOrderCount(123, @cnt); -
OUT参数在调用前可以是NULL,过程内必须赋值,否则返回NULL - 如果想复用已有变量名,建议统一用
@前缀的用户变量,避免和参数名混淆
PostgreSQL 用 OUT 参数或 RETURNS 返回多值
PostgreSQL 没有“输出参数”概念,而是把 OUT 参数当作函数返回值的一部分。它更倾向用 RETURNS TABLE 或 RETURNS record 来表达多输出。
单值输出可这样写:
CREATE OR REPLACE FUNCTION get_order_count(p_customer_id INT)
RETURNS INT AS $$
DECLARE
v_count INT;
BEGIN
SELECT COUNT(*) INTO v_count
FROM orders
WHERE customer_id = p_customer_id;
RETURN v_count;
END;
$$ LANGUAGE plpgsql;
若要模拟 SQL Server 风格的多输出参数,得用 OUT + RETURNS record:
CREATE OR REPLACE FUNCTION get_order_summary(
p_customer_id INT,
OUT order_count INT,
OUT total_amount NUMERIC
) AS $$
BEGIN
SELECT COUNT(*), COALESCE(SUM(amount), 0)
INTO order_count, total_amount
FROM orders
WHERE customer_id = p_customer_id;
END;
$$ LANGUAGE plpgsql;
- 调用时必须用
SELECT *才能拿到所有OUT字段:SELECT * FROM get_order_summary(123); - 不能像 SQL Server 那样用变量接收,PostgreSQL 的
OUT是返回结构的一部分 - 如果只想要一个值,优先用
RETURNS type,语义更清晰,性能也略好
跨数据库移植时,OUTPUT / OUT / RETURNS 的行为差异容易被忽略
同一个业务逻辑,在三个主流数据库里实现输出,光是关键字和调用方式就完全不同。更麻烦的是语义差异:
- SQL Server 的
OUTPUT允许传入已初始化的变量,过程可读可写;MySQL 的OUT在调用前未赋值就是NULL,且过程内不赋值就保持NULL - PostgreSQL 的
OUT参数本质上是返回值别名,无法在函数内“读取”传入的初始值(因为根本没传) - SQL Server 支持多个
OUTPUT参数,MySQL 和 PostgreSQL 都支持,但调用语法完全不同,自动化迁移工具很容易漏掉
真正难的不是写出来,而是确认“这个变量到底有没有被更新”——尤其在嵌套调用或异常路径下,务必在每个分支都显式赋值,否则不同数据库表现可能完全不一致。











