【问题标题】:PostgreSQL casting issue on data typePostgreSQL关于数据类型的转换问题
【发布时间】:2015-10-14 23:50:36
【问题描述】:

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

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 行: 左外连接 form_field ff ON ff.field_name = weight ^ 提示:没有运算符匹配给定的名称和参数类型。你可能需要 添加显式类型转换。查询:插入 患者表格值(患者表格 ID,表格模板字段 ID, field_value) 选择 pf.id AS Patient_form_id, ftf.id AS form_template_field_id, c.weight AS field_value FROM casesheetcomplaints c LEFT OUTER JOIN form_field ff ON ff.field_name = weight 左外连接 form_template_field ftf ON ftf.form_field_id = ff.id 左外连接 patient_form pf on c.patient_id = pf.patient_id AND pf.created_date = c.reg_date 其中 c.weight 是 NOT NULL AND ftf.id IS NOT NULL GROUP BY c.patient_id, c.weight,pf.id,ftf.id

【问题讨论】:

  • 为了减少引用问题,您可以使用 format() 函数代替 concat() 构造(否则您可以使用 quote_ident() 和 quote_literal() )

标签: postgresql


【解决方案1】:

帮自己一个忙,然后:

  • 对函数体使用美元报价
  • 正确格式化函数体
  • 使用format() 函数代替concat()
  • 对 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子句是没用的:一个表不能有多个同名的列。

【讨论】:

    【解决方案2】:
    LEFT OUTER JOIN form_field ff ON ff.field_name = cast('',r.column_name,'' as character varying)
    

    将值类型转换为字符变化

    【讨论】:

      【解决方案3】:

      请注意,错误是由于:

      ON ff.field_name = weight
      

      我想应该是:

      ON ff.field_name = 'weight'
      

      所以你必须使用转义单引号的方法。请参阅this question 了解如何插入单引号。

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

      【讨论】:

      • 是的,但是值(权重)将是其他一些数据库的列,它的数据类型会有所不同。所以数据类型不匹配。我该如何处理多种数据类型。
      • 但是您想将 field_name 与字段 weigth 还是与该字段的名称(即“重量”)进行比较?通过阅读 ff.field_name 我了解您想将其与名称进行比较。
      猜你喜欢
      • 1970-01-01
      • 2011-11-04
      • 2020-09-25
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多