T-SQL与PL/pgSQL在存储过程编写上存在根本差异:执行模型、变量作用域和事务控制粒度不同,照搬逻辑易致CALL失败、变量未定义或事务意外提交;变量声明、赋值语法、字符串拼接、事务控制及错误处理机制均不兼容。

直接说结论:T-SQL 和 PL/pgSQL 在存储过程编写上不是“语法微调”问题,而是执行模型、变量作用域、事务控制粒度三者根本不同。照搬逻辑大概率导致 CALL 失败、变量未定义、或事务意外提交。
变量声明与作用域必须显式区分
T-SQL 使用 @ 前缀声明会话级变量,可在批处理中跨语句访问;PL/pgSQL 的变量在 DECLARE 块内声明,仅在当前 BEGIN ... END 块内有效,且不加前缀。
- T-SQL 中
DECLARE @user_id INT; SELECT @user_id = id FROM users WHERE name = 'A';后,@user_id可在后续任意语句中引用 - PL/pgSQL 必须写成
DECLARE user_id INT; BEGIN SELECT id INTO user_id FROM users WHERE name = 'A';,一旦跳出BEGIN就失效 - 常见错误:把 T-SQL 的
@var直接抄进 PL/pgSQL,报错column "var" does not exist或unrecognized parameter
赋值语法和 SQL 内嵌方式完全不同
T-SQL 允许用 SELECT @var = col 一次性完成查询+赋值;PL/pgSQL 强制使用 SELECT ... INTO,且不能混用 = 赋值表达式。
PostgreSQL 18.4 官方 Ubuntu 安装包现已发布,这是目前最新的稳定版本。推荐通过官方 APT 仓库安装:先执行 sudo apt update 更新索引,再运行 sudo apt install postgresql-18 即可完成部署。新版本引入了异步 I/O 子系统,在顺序扫描与 VACUUM 场景下性能提升显著,同时支持 UUID v7 原生生成函数与虚拟生成列。
- T-SQL:
SELECT @status = status FROM orders WHERE id = 123合法 - PL/pgSQL:
SELECT status INTO status_var FROM orders WHERE id = 123才合法;写成status_var = (SELECT status FROM ...)会报错 - 字符串拼接也不同:T-SQL 用
+,PL/pgSQL 用||;误用会导致operator does not exist: text + text
CALL 与事务边界行为差异极大
PostgreSQL 11+ 的 PROCEDURE 支持 COMMIT/ROLLBACK,但函数(FUNCTION)禁止;T-SQL 存储过程中任何地方都能发 COMMIT,且默认自动开启隐式事务。
- 若把 T-SQL 中带
COMMIT的逻辑直接迁移到 PL/pgSQL 函数里,会触发ERROR: cannot commit inside a function - 想在 PL/pgSQL 中控制事务,必须改用
CREATE PROCEDURE(而非CREATE FUNCTION),并确保客户端用CALL调用,而非SELECT - 另一个坑:T-SQL 的
GO是客户端批处理分隔符,PL/pgSQL 完全不识别——删掉GO,否则报错syntax error at or near "GO"
最易被忽略的是错误处理机制:T-SQL 依赖 @@ERROR 和 TRY...CATCH,PL/pgSQL 必须用 EXCEPTION 块捕获具体 SQLSTATE;没做这层映射,异常就静默吞掉了。

















