PostgreSQL对数据类型的转换问题

时间:2015-07-24 10:34:12

标签: postgresql

这是我的代码,我有动态列名,而我加入其他表时会出现数据类型不匹配。我该如何解决这个问题..

CREATE OR REPLACE FUNCTION migratePartnerAdvertiser() RETURNS int4 AS '
DECLARE r RECORD;
BEGIN
  FOR r IN
    select distinct COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS
    where TABLE_NAME = ''casesheetcomplaints'' and table_schema=''public''
  LOOP
    EXECUTE concat(''INSERT INTO patient_form_value(patient_form_id,
                                                    form_template_field_id, field_value) 
      select  pf.id AS patient_form_id, ftf.id AS form_template_field_id, c.'',
              r.column_name, '' AS field_value  
      FROM casesheetcomplaints c 
      LEFT OUTER JOIN form_field ff ON ff.field_name = '',r.column_name,''
      LEFT OUTER JOIN form_template_field ftf ON ftf.form_field_id = ff.id
      LEFT OUTER JOIN patient_form pf on c.patient_id = pf.patient_id
                                      AND  pf.created_date = c.reg_date 
      where c.'', r.column_name, '' IS NOT NULL AND ftf.id IS NOT NULL
      GROUP BY c.patient_id, c.'', r.column_name, '', pf.id, ftf.id'');
  END LOOP;
  return 1;
END;
' LANGUAGE plpgsql;

错误讯息:

  

错误:运算符不存在:字符变化=数字第4行:   LEFT OUTER JOIN form_field ff ON ff.field_name = weight                                                           ^提示:没有运算符匹配给定的名称和参数类型。你可能需要   添加显式类型转换。 QUERY:INSERT INTO   patient_form_value(patient_form_id,form_template_field_id,   field_value)选择pf.id AS patient_form_id,ftf.id AS   form_template_field_id,c.weight AS field_value FROM   caseheetcomplaints c LEFT OUTER JOIN form_field ff ON ff.field_name   = weight LEFT OUTER JOIN form_template_field ftf ON ftf.form_field_id = ff.id LEFT OUTER JOIN patient_form pf on c.patient_id = pf.patient_id AND pf.created_date = c.reg_date where c.weight IS   NOT NULL和ftf.id IS not NULL GROUP by c.patient_id,   c.weight,pf.id,ftf.id

3 个答案:

答案 0 :(得分:1)

帮自己一个忙,并且:

  • 为您的函数正文使用美元引用
  • 正确格式化您的功能正文
  • 使用format()功能代替concat()
  • 将CAPITALS用于SQL标识符,将小写用于其他所有内容

如果您执行上述所有操作,您的功能将变得更具可读性:

CREATE FUNCTION migratePartnerAdvertiser() RETURNS int4 AS $$
DECLARE
  r RECORD;
BEGIN
  FOR r IN
    SELECT column_name FROM information_schema.columns
    WHERE table_name = 'casesheetcomplaints' AND table_schema = 'public'
  LOOP
    EXECUTE format('
      INSERT INTO patient_form_value(patient_form_id, form_template_field_id, field_value) 
        SELECT pf.id AS patient_form_id,
               ftf.id AS form_template_field_id,
               c.%1$I AS field_value  
        FROM casesheetcomplaints c 
        LEFT JOIN form_field ff ON ff.field_name = %1$L
        LEFT JOIN form_template_field ftf ON ftf.form_field_id = ff.id
        LEFT JOIN patient_form pf ON c.patient_id = pf.patient_id AND pf.created_date = c.reg_date 
        WHERE c.%1$I IS NOT NULL AND ftf.id IS NOT NULL', r.column_name);
  END LOOP;
  RETURN 1;
END;
$$ LANGUAGE plpgsql;

请注意r.column_name列在format()函数的末尾,并且只要遇到%,就会插入查询中。这种情况多次发生,因此%1$位置参数。您可以将它用作标识符%1$I和文字%1$L,它可以消除您的错误。

我还删除了GROUP BY子句,因为你没有聚合任何东西。如果要删除重复项,请改用DISTINCT子句。循环查询中的DISTINCT子句是无用的:单个表不能有多个具有相同名称的列。

答案 1 :(得分:1)

LEFT OUTER JOIN form_field ff ON ff.field_name = cast('',r.column_name,'' as character varying)

将值变为字符变化

答案 2 :(得分:0)

请注意,错误是由于:

ON ff.field_name = weight
我想象的应该是:

ON ff.field_name = 'weight'

所以你必须使用一种逃避单引号的方法。有关如何插入单引号,请参阅this question

另一个建议是:永远不要使用'来分隔函数体,因为它与在体内使用单引号的需要相冲突,而是使用更常见的$$