如何在postgresql中运行多个更新的语句

时间:2017-08-01 09:13:34

标签: postgresql function dynamic parameters

我尝试使用参数运行此脚本,但它不断抛出语法错误。语法有什么问题。还有什么是调用此函数的正确方法。我需要一个输出告诉我更新语句被成功执行了。我尝试了“select function_name(schema_name.TABLE_NAME);”。让我补充说我是初学者,并且对任何反馈都持开放态度。如有必要,还将提供更多详细信息。

CREATE OR REPLACE FUNCTION function_name (TABLE_NAME IN character varying)
RETURNS text AS $SQLQuery$
DECLARE SQLQuery text;
BEGIN

SQLQuery = 
' UPDATE '|| TABLE_NAME || ' SET column1=''0''
WHERE column1 is null;' ||

' UPDATE '|| TABLE_NAME || ' SET column2='value'
WHERE column2=''different value'';' ||

--multiple update statements later

Execute  SQLQuery;
Return SQLQuery;

END;
$SQLQuery$
LANGUAGE plpgsql;

更新: 这是我在调用测试函数时得到的错误

ERROR:  missing FROM-clause entry for table "schema_name"
LINE 2: select test_function(schema_name.TABLE_NAME);
                             ^
********** Error **********

ERROR: missing FROM-clause entry for table "schema_name"
SQL state: 42P01

它正在以表的形式读取函数吗? 我也收到语法错误说 EXECUTE列不存在或该函数不存在 即使我刚宣布它。

3 个答案:

答案 0 :(得分:0)

要在选址常量中使用单引号,必须通过将它们加倍来对它们进行转义。

而不是

' SET column1='0''

你必须写

' SET column1=''0'''

答案 1 :(得分:0)

像往常一样:

CREATE OR REPLACE FUNCTION function_name (schema_name text,TABLE_NAME IN character varying)
RETURNS text AS $SQLQuery$
DECLARE 
  c int;
  rtn text :='';
BEGIN

execute format(' UPDATE %I.%I SET column1=''0'' WHERE column1 is null;',schema_name,TABLE_NAME);
get diagnostics c = row_count;
raise info '%', 'affected: '||c;
rtn = rtn + 'affected: '||c||chr(10);
--repeat above construct for multiple update statement
return rtn;
END;
$SQLQuery$
LANGUAGE plpgsql;

并建议。我和你一样是新手,但我学会遵循几条规则,这对我很有帮助:

  • 使用动态sql使用format来避免sql注入
  • 不要过于复杂化(例如,您正在寻找的功能已经在UPDATE语句中 - 检查输出。如​​果要检查生成的行使用,UPDATE ... RETURNING *构造。
  • 练习很好,但阅读概念很珍贵。

在您的POST select function_name(schema_name.TABLE_NAME);中无效,因为您使用 schema_name.TABLE_NAME 而没有引号,但即使您放置它们,您的功能也很容易受到影响 - 如果您运行{会发生什么? {1}}?..

答案 2 :(得分:0)

您正在尝试传递SQL标识符,但您的函数将字符串作为参数。您应该将其更改为: select test_function('schema_name.TABLE_NAME');

您可以尝试以下功能作为您尝试做的任何事情的基础。

/* You need to split table and schema name
   or you might get errors when using names that aren't lower case.

   This: 'public.TEST1' would be translated to: "public.TEST1"
   that is different table from public.test1
*/
CREATE OR REPLACE FUNCTION multi_update_stuff(schema_name varchar, table_name varchar)
/* We will return set of multiple columns. One possible method is to return table.
   First column shows executed query, second if it returned no errors (true)
*/
RETURNS TABLE(SQLQuery text, result boolean)
AS $body$
DECLARE
  /* Declare arroy of queries that we will iterate and execute later.
     We use format() to build query from template and fill it with values.
     %1$I can be described as "put first value here and treat it as object identifier"
     %3$L can be described as "put third value here and treat it as SQL literal"
  */
  SQLQueries text[] := array[
    /* First query */
    format('UPDATE %1$I.%2$I SET column1 = %3$L WHERE column1 is null;',
           schema_name, table_name, '0'),
    /* Second query */
    format('UPDATE %1$I.%2$I SET column2 = %3$L WHERE column2 = %4$L;',
           schema_name, table_name, 'value', 'different value'),
    /* Third query, to see error free result */
    'SELECT 1'];
BEGIN
  /* Iterate our array */
  FOREACH SQLQuery IN ARRAY SQLQueries
  LOOP
    /* Start transaction block */
    BEGIN
      EXECUTE SQLQuery;
      result := true;
    /* Catch error if any */
    EXCEPTION
      WHEN others THEN
        result := false;
    END;
    /* Return row with whatever is assigned to variables listed in RETURNS.
       In this case SQLQuery was already assigned by FOREACH.
    */
    RETURN NEXT;
  END LOOP;
END;
$body$
LANGUAGE plpgsql;

SELECT * FROM multi_update_stuff('schema_name', 'TABLE_NAME')