删除以tablename作为参数的行的函数

时间:2013-04-16 04:54:57

标签: postgresql stored-procedures sql-injection plpgsql sql-function

我想创建一个函数:

 CREATE OR REPLACE FUNCTION medibv.delAuto(tableName nvarchar(50), columnName nvarchar(100),value 
 nvarchar(100))
 RETURNS void AS

$BODY$ 
begin 
DELETE from tableName  where columnName=value 

end; 
$BODY$

LANGUAGE plpgsql VOLATILE;

我有以下参数:tableName, columnName, value
我希望tableName作为PostgreSQL中的表。

2 个答案:

答案 0 :(得分:3)

CREATE OR REPLACE FUNCTION medibv.delauto(tbl regclass, col text, val text
                                         ,OUT success bool)
  RETURNS bool AS
$func$ 
BEGIN

EXECUTE format('
   DELETE FROM %s
   WHERE  %I = $1
   RETURNING TRUE', tbl, col)
USING   val
INTO    success;

RETURN;  -- optional in this case

END
$func$ LANGUAGE plpgsql;

呼叫:

SELECT medibv.delauto('myschema.mytbl', 'my_txt_col', 'foo');

返回TRUENULL

  • Postgres中没有nvarchar类型。你可能会想到SQL Server。相当于varchar,但大多数时候您只需使用text

  • regclass是注册表名的专用类型。它非常适用于自动且最有效地阻止表名的 SQL注入的情况。更多在下面的相关答案中。

  • 列名仍然易于SQL注入。我使用format(%I)清理函数。

  • format()需要PostgreSQL 9.1 +。

  • 您的功能未报告发生了什么。可以找到并删除一行或多行。或者根本没有。作为最低限度,我添加了boolean OUT列,如果删除了一行或多行,则会TRUE。因为(quoting the manual here):

      

    如果返回多行,则只会将第一行分配给INTO变量。

  • 最后,使用 USING EXECUTE传递。不要来回投掷。这是低效的,容易出错,再次出现在SQLi上。

  • 在这个密切相关的答案中找到更多解释和链接:
    Table name as a PostgreSQL function parameter

答案 1 :(得分:1)

使用EXECUTE运行动态命令:

CREATE OR REPLACE FUNCTION medibv.delAuto(tableName nvarchar(50), columnName nvarchar(100),value 
 nvarchar(100))
 RETURNS void AS

$BODY$ 
begin 
EXECUTE 'DELETE FROM ' || tableName || ' WHERE ' || columnName || '=' || value; 

end; 
$BODY$

LANGUAGE plpgsql VOLATILE;