【问题标题】:Autopartitioning Postgresql for Zabbix为 Zabbix 自动分区 Postgresql
【发布时间】:2018-08-24 06:56:10
【问题描述】:

目标,自动分区 7 天。并在 14 天后删除旧分区。在这个例子中,一切正常。但是,当我尝试写入表单的数据时:

insert into history_str (itemid, clock, ns, value) values (40,151,3722, '3.0.3');

我收到一个错误

ERROR: syntax error at or near ".3"
LINE 1: ... istory_str_2018_02_07 values (40,151,3.0.3,3722 ...
                                                    ^
QUERY: INSERT INTO history_str_2018_02_07 values (40,151,3.0.3,3722);
CONTEXT: PL / pgSQL function create_partition_other () line 37 at EXECUTE

这是实际的代码示例

CREATE OR REPLACE FUNCTION create_partition() RETURNS trigger AS
  $BODY$
    DECLARE
      partition_name TEXT;
      partition_week TEXT;
      partitions_names TEXT;
      date_search TEXT;
      sql_search TEXT;
      var_data TEXT;
      typeof BOOL;

    BEGIN
      partition_week := to_char(to_timestamp(NEW.clock),'IW');
      RAISE INFO 'Week now: %',partition_week;
      partition_name := TG_TABLE_NAME || '_' || to_char(to_timestamp(NEW.clock),'YYYY_MM') || '_' || partition_week;
      RAISE INFO 'Master Table: %',TG_TABLE_NAME;
      RAISE INFO 'Partit. name: %',partition_name;

      IF NOT EXISTS(SELECT relname FROM pg_class WHERE relname = partition_name) THEN
        RAISE INFO 'Create table';
        EXECUTE 'CREATE TABLE ' || partition_name || ' (check (clock >= ' || quote_literal(NEW.clock) || ' AND clock < ' || quote_literal(NEW.clock + integer '7' * integer '86400') || ')) INHERITS (' || TG_TABLE_NAME || ');';
        EXECUTE 'INSERT INTO create_tables_date (name,date) values (' || quote_literal(partition_name) || ',' || quote_literal(to_timestamp(NEW.clock)) || ');';
        date_search := quote_literal(date (to_char(to_timestamp(NEW.clock),'YYYY_MM_DD'))-integer '7');
        RAISE INFO 'Search data: %',date_search;
        sql_search := 'SELECT name FROM create_tables_date WHERE date < ' || date_search || ';';
        for partitions_names in EXECUTE sql_search LOOP
          IF partitions_names IS NOT NULL THEN
            RAISE INFO 'DROP, DELETE: %',partitions_names;
            EXECUTE 'DROP TABLE ' || partitions_names || ';';
            EXECUTE 'DELETE FROM create_tables_date WHERE name=' || quote_literal(partitions_names) || ';';
          END IF;
        END LOOP;
      END IF;
      RAISE INFO 'Value: %',NEW.value;

      var_data := 'INSERT INTO ' || partition_name || ' values ' || NEW || ';';
      RAISE INFO 'SQL: %',var_data;
      EXECUTE var_data;
      RETURN NULL;
    END;
  $BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

在NEW.value中写入值的时候发现问题。将[(), \]中的字符替换为_后,问题就解决了。

也就是说,我在插入NEW.value之前重新定义

NEW.value := quote_literal(regexp_replace(NEW.value,'[(),\ ]','_','g'));

但是,如果我尝试写入具有列值的表,并且没有其他表,我必须为每个表编写许多相同的函数。有什么不好。 你知道为什么这些符号会出现这种情况吗? PostgreSQL 9.5.9

【问题讨论】:

    标签: postgresql partitioning partition zabbix


    【解决方案1】:

    您可以尝试USING 并用星号扩展行:

    var_data := 'INSERT INTO ' || partition_name || ' values ($1.*);';
    RAISE INFO 'SQL: %',var_data;
    EXECUTE var_data using new;
    

    【讨论】:

    • 非常感谢您的回答。我尝试了您的建议,但出现错误:INFO: SQL: INSERT INTO history_str_2018_03_11 values ($1.*);错误:没有参数 $1 LINE 1: INSERT INTO history_str_2018_03_11 values ($1.*);
    • @КонстантинВелопокатуновичь 您确定代码中的这两行都已更改吗?
    • :) 非常感谢您反复推我的鼻子。我忘记了最后一行的更改。实际上一切正常。但是由于发生了什么事,为什么新的不适合,我的版本出了什么问题?谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多