sql - SQL select 语句产生与 PL/pgSQL FOR 循环相同的结果
问题描述
我很难理解何时使用 PL/pgSQLFOR
循环与常规 SQL。
这个问题肯定显示了我的天真,但这是我感到困惑的地方:
给定这张表:
CREATE TABLE bins AS
SELECT * FROM GENERATE_SERIES(1, 10) AS id;
如果我想id
在每一行的字段中添加一个加 1,我会这样做:
select id+1 from bins;
这将正确返回
2
3
4
5
6
7
8
9
10
11
现在,如果我为此操作使用 PL/pgSQL 函数,它看起来像这样:
CREATE OR REPLACE FUNCTION add_one(
n integer
)
RETURNS VOID AS $$
DECLARE
rec RECORD;
BEGIN
FOR rec IN SELECT id
FROM bins
LOOP
RAISE NOTICE '%', rec.id+n;
END LOOP;
END;
$$ LANGUAGE plpgsql;
那么那么
select add_one(1)
会产生
-- Executing query:
select add_one(1)
NOTICE: 2
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE: 3
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE: 4
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE: 5
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE: 6
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE: 7
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE: 8
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE: 9
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE: 10
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE: 11
CONTEXT: PL/pgSQL function add_one(integer) line 9 at RAISE
所以我的问题是,SQL select 语句在某种程度上就像一个 for 循环,因为在这个例子中,它为每一行添加了一个 1 ......这与 PL/pgSQL 函数中发生的事情是一样的。这是一个准确的描述吗?
解决方案
Your description is accurate.
What is probably your biggest problem at this point is to understand the non-procedural nature of SQL. In this language you do not specify the steps required to reach a result, you only describe the result you want.
So the SQL statement you used above that you want id
, increased by one, for every row in the table. If the database does this by running a loop internally or by an act of god is not your primary focus.
This is weird for many procedural programmers in the beginning, but it makes life better once you get used to it: you don't have to know all the database internals to figure out the best way to process a query. The optimizer does that for you, and usually better than you could do it yourself.
Of course it is healthy curiosity to want to know how a query is processed internally. For that you use the EXPLAIN
statement. This is particularly necessary to analyze and fix performance problems.
The rule of thumb is that it is usually better to perform as much of the work as possible in one bigger SQL statement than in many simple small ones tied together with application code. This is because there is less overhead this way, but also because a bigger statement often opens more ways to the optimizer. For example, nested loops are the simplest, but not always the best way to solve a problem.
推荐阅读
- amazon-web-services - 如何在不删除现有内容的情况下向 AWS Lambda 添加环境变量?
- javascript - material-ui 点击一个时关闭所有其他卡片内容
- c# - Asp.Net Mvc Identity&Owin 真正的双重身份验证方式
- swift - 如何将 NSDateComponent 作为函数参数传递
- typescript - 你如何在类型 T 和 U 上声明一个函数泛型,它不允许 T 和 U 的空交集
- python - 来自单个 CSV 文件源的多个列表推导
- python - mysql工作台无法导入pyodbc
- javascript - 内容安全策略 jQuery 加载 PHP Echo Nonce
- sql - 在 mySQL 工作台中创建过程语句时出现错误 1064
- excel - Remove the commas, spaces and "NULL" string to 0(Zero) from Column