我想在postgresql中编写一个简单的函数,它检查我的表是否存在,如果存在,则清除其所有行。在postgresql文档中,我看到我可以通过$加上arg数来引用我的参数,但它在函数创建过程中给出了一个错误。
这是我的功能:
CREATE OR REPLACE FUNCTION delete_if_exists(table_name text) RETURNS void
AS $$
BEGIN
IF EXISTS(SELECT * FROM $1)
THEN
delete from $1;
END IF;
RETURN;
END;
$$ LANGUAGE plpgsql;
答案 0 :(得分:0)
函数中的变量不是简单地插入到字符串中,而是作为参数传递给准备好的查询。因此,您无法直接在可能会更改计划的部分查询中使用它们,例如表名和列名。
为了做到这一点,你需要改为使用动态SQL ,即以编程方式构建一个字符串,并执行它。请参阅Executing Dynamic SQL in the manual。
创建动态SQL时应始终非常小心,因为很容易意外地产生安全问题。至少,您应该使用正确的转义机制,但您可能还希望将函数所期望的表名称列入白名单或模式匹配。
使用the format()
function %I
占位符正确引用的示例:
EXECUTE format('delete from %I;', $1);
请注意,您还可以使用变量的名称,而不是位置标识符,这在较长的函数中更容易阅读:
EXECUTE format('delete from %I;', table_name);
我不会尝试调整你的完整例子,因为我认为它无论如何都是一个过于简化的例子,因为它实际上并没有写成。
答案 1 :(得分:0)
如果将标识符(表名,列名)传递给函数,则需要execute the query dynamically。此外,如果没有过滤器DELETE FROM
,您应该使用TRUNCATE
,因为这样会更快并且会清理您的硬盘(在不利方面,更改无法撤消)。
CREATE FUNCTION delete_if_exists(table_name text) RETURNS void AS $$
BEGIN
-- Just try to TRUNCATE
EXECUTE format('TRUNCATE %I', table_name);
EXCEPTION
WHEN OTHERS THEN
NULL; -- If the table does not exist, an error is thrown, just ignore it
END;
$$ LANGUAGE plpgsql;