简体   繁体   English

Postgresql函数与表作为输入? 是plpgsql函数中的动态SQL的方法吗?

[英]Postgresql function with table as input? Is dynamic SQL in a plpgsql function the way to go?

I have a common situation that comes up where I want to join with a table moredata. 我有一个常见的情况出现在我想加入表moredata的地方。 To give the simplest example, imagine I have: 举一个最简单的例子,假设我有:

SELECT *
FROM x 
JOIN moredata d on x.yyyymmdd = d.yyyymmdd

x will vary while moredata stays the same. x会有所不同,而moredata保持不变。 What's a good way stylistically to reuse code, automate the above so that I can apply it to different tables (eg. do the same thing on table 'y' instead of 'x')? 风格上重用代码的好方法是什么,自动化上面的代码以便我可以将它应用到不同的表中(例如,在表'y'而不是'x'上做同样的事情)?

One way would be to write a plpgsql function using dynamic SQL that operates on the name of the table. 一种方法是使用动态SQL编写plpgsql函数,该函数对表的名称进行操作。 Something like: 就像是:

CREATE FUNCTION joinmoredata(tblname text) RETURNS TABLE(...) AS $$
BEGIN
  RETURN QUERY EXECUTE format('SELECT * FROM %I JOIN moredata on ...', tblname);
END;
$$ LANGUAGE plpgsql;

But then you couldn't apply it to a derived table or a CTE. 但是,您无法将其应用于派生表或CTE。 Is there a better way? 有没有更好的办法? Or is dynamic SQL the best way to reuse code in this situation? 或者动态SQL是在这种情况下重用代码的最佳方法?

(Note, the actual query is a lot more complicated than SELECT * FROM x JOIN moredata d on x.yyyymmdd = d.yyyymmdd which is why I want to reuse code.) (注意,实际查询要比SELECT * FROM x JOIN moredata d on x.yyyymmdd = d.yyyymmdd复杂得多,这就是我想重用代码的原因。)

As long as you use the same column names with the same data types from each table in place of x and return the same row type, that's a good candidate for dynamic SQL. 只要在每个表中使用相同的列名和相同的数据类型代替x并返回相同的行类型,那么它就是动态SQL的理想选择。 Exactly like you already have in your question. 完全像你已经在你的问题中。 Your use of format() with %I suggests you are aware of how to sanitize identifiers avoid syntax errors and SQL injection. 您对%Iformat()使用表明您知道如何清理标识符以避免语法错误和SQL注入。

You need to have a plan for privilege management. 您需要有一个特权管理计划。 And I would pass schema-qualified table names or data type regclass to avoid confusion with table name resolution and possibly other tables with the same name in a different schema. 我会传递模式限定的表名或数据类型regclass以避免混淆表名解析和可能在不同模式中具有相同名称的其他表。

Closely related, with more details: 密切相关,有更多细节:

If it gets more complicated - varying column names and types - you can always concatenate query strings in a client program ... 如果它变得更复杂 - 变化的列名和类型 - 你总是可以在客户端程序中连接查询字符串......

I can only say that I use dynamic SQL any time I need to reuse bigger parts of SQL code and change only something in WHERE clause or table names etc. And it works OK and I do this way also very complicated CTE queries containing also INSERTs or UPDATESs and it works. 我只能说我在任何时候都需要重用SQL代码的更大部分并且只改变WHERE子句或表名等中的某些东西时使用动态SQL。它工作正常我也这样做也很复杂的CTE查询也包含INSERT或更新,它的工作原理。 So I would vote for dynamic SQL. 所以我会投票支持动态SQL。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM