在数据库世界里,有好几种语言可以扩展普通SQL的能力,让你直接在数据库里写完整的业务逻辑。每种语言都为自己的平台量身定制,但总体来说它们解决的都是类似的问题——让数据操作自动化、更简单、更快。在这些语言里,有PostgreSQL的PL/pgSQL、Oracle的PL/SQL和SQL Server的T-SQL。每种都有自己的特点、优点和小坑,下面咱们就来聊聊这些。
PL/pgSQL(Procedural Language/PostgreSQL Structured Query Language)是PostgreSQL自带的过程式编程语言。它的主要任务就是扩展SQL的功能,让开发者能用变量、循环、控制结构和错误处理块来写代码。这让PL/pgSQL成为在数据库端实现复杂业务逻辑的强大工具。
PL/SQL(Procedural Language/SQL)是Oracle数据库内置的过程式编程语言。它也能处理数据、创建过程、函数和包。PL/SQL因为经过了几十年的打磨和有丰富的工具生态,被认为是非常成熟的语言。
T-SQL(Transact-SQL)是微软为SQL Server开发的语言。它是在标准SQL基础上扩展的,支持变量、控制结构和其他过程式编程元素。T-SQL在事务、游标和JSON处理方面有自己的特点。
PL/pgSQL、PL/SQL和T-SQL的相似点
乍一看,这三种语言都挺像的。这也不奇怪,毕竟它们的目标都是一样的——让开发者能在数据库里实现业务逻辑。来看看它们的主要相似点:
代码块语法
这三种语言都支持结构化的过程式代码写法。主要元素有:
- 变量声明。
- 主执行块(
BEGIN ... END)。 - 异常处理支持。
变量
你可以在这三种语言里声明和使用变量。比如PL/pgSQL里声明变量的例子:
DECLARE student_id INT; BEGIN student_id := 10; END;PL/SQL和T-SQL里也能类似操作。
控制结构
所有语言都支持
IF...THEN、CASE、LOOP、FOR、WHILE,可以写很复杂的算法。函数和过程
可以创建和调用自定义函数和过程,这些可以返回单个值,也可以返回表。
PL/pgSQL、PL/SQL和T-SQL的不同点
开发者经常会遇到要从一个数据库迁移到另一个的情况。这时候了解语言的细节就很重要了。下面咱们来拆解下关键区别。
变量声明
PL/pgSQL:变量在DECLARE块里声明。赋值用:=。
DECLARE
total_students INT;
BEGIN
total_students := 5;
END;
PL/SQL:声明方式和PL/pgSQL差不多,但变量类型可以用%TYPE继承表字段类型。
DECLARE
student_name students.name%TYPE;
BEGIN
student_name := 'John';
END;
T-SQL:变量用DECLARE关键字声明,赋值用SET或SELECT。
DECLARE @total_students INT;
SET @total_students = 5; -- 或者
SELECT @total_students = COUNT(*) FROM students;
错误处理
PL/pgSQL:用EXCEPTION块处理错误。比如:
BEGIN
SELECT * INTO my_var FROM nonexistent_table;
EXCEPTION
WHEN others THEN
RAISE NOTICE '发生错误啦!';
END;
PL/SQL:也是用EXCEPTION,但错误分类更细。
BEGIN
SELECT * INTO my_var FROM nonexistent_table;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('没找到数据!');
END;
T-SQL:用TRY...CATCH结构。
BEGIN TRY
SELECT 1/0; -- 除零错误
END TRY
BEGIN CATCH
PRINT '发生错误啦!';
END CATCH;
游标操作
PL/pgSQL:游标是隐式的,可以直接在循环里用。
FOR row IN SELECT * FROM students LOOP
RAISE NOTICE '学生: %', row.name;
END LOOP;
PL/SQL:游标需要显式声明。比如:
DECLARE
CURSOR student_cursor IS SELECT * FROM students;
student_row students%ROWTYPE;
BEGIN
OPEN student_cursor;
FETCH student_cursor INTO student_row;
CLOSE student_cursor;
END;
T-SQL:游标用CURSOR关键字声明。
DECLARE student_cursor CURSOR FOR SELECT name FROM students;
OPEN student_cursor;
FETCH NEXT FROM student_cursor;
CLOSE student_cursor;
DEALLOCATE student_cursor;
事务处理
PL/pgSQL:事务用BEGIN、COMMIT、ROLLBACK控制。
PL/SQL:事务同样用COMMIT、ROLLBACK,还支持SAVEPOINT。
T-SQL:用BEGIN TRANSACTION标记事务开始。
JSON支持
PL/pgSQL:通过JSON和JSONB类型强力支持JSON。比如:
SELECT data->>'key' FROM json_table;
PL/SQL:JSON支持比较晚,灵活性稍差。
T-SQL:通过JSON_QUERY、JSON_VALUE等函数处理JSON很方便。
什么时候用PL/pgSQL、PL/SQL或T-SQL?
PL/pgSQL:
- 如果你的数据库是PostgreSQL,选它没跑。
- 处理大数据量很合适,支持强大的数据类型(
JSONB、数组)。 - 开源生态,灵活性高。
PL/SQL:
- Oracle产品的首选。
- 数据处理生态丰富(包、内置过程)。
T-SQL:
- 用于Microsoft SQL Server。
- 和微软应用、Microsoft Azure集成很棒。
PL/pgSQL、PL/SQL和T-SQL实现同一任务的例子
任务:统计学生数量并返回结果
PL/pgSQL:
CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
total INT;
BEGIN
SELECT COUNT(*) INTO total FROM students;
RETURN total;
END;
$$ LANGUAGE plpgsql;
PL/SQL:
CREATE OR REPLACE FUNCTION count_students RETURN NUMBER IS
total NUMBER;
BEGIN
SELECT COUNT(*) INTO total FROM students;
RETURN total;
END;
T-SQL:
CREATE FUNCTION count_students()
RETURNS INT
AS
BEGIN
DECLARE @total INT;
SELECT @total = COUNT(*) FROM students;
RETURN @total;
END;
现在你已经大致了解了PL/pgSQL、PL/SQL和T-SQL的区别。每种语言都有自己的特点和适用场景,让它变得独特。选择哪种语言(以及数据库)总是要看你的需求和项目的具体情况。
GO TO FULL VERSION