【问题标题】:updating table rows in postgres using subquery使用子查询更新 postgres 中的表行
【发布时间】:2011-09-09 12:58:39
【问题描述】:

使用 postgres 8.4,我的目标是更新现有表:

CREATE TABLE public.dummy
(
  address_id SERIAL,
  addr1 character(40),
  addr2 character(40),
  city character(25),
  state character(2),
  zip character(5),
  customer boolean,
  supplier boolean,
  partner boolean

)
WITH (
  OIDS=FALSE
);

最初我使用插入语句测试了我的查询:

insert into address customer,supplier,partner
SELECT  
    case when cust.addr1 is not null then TRUE else FALSE end customer, 
    case when suppl.addr1 is not null then TRUE else FALSE end supplier,
    case when partn.addr1 is not null then TRUE else FALSE end partner
from (
    SELECT *
        from address) pa
    left outer join cust_original cust
        on (pa.addr1=cust.addr1 and pa.addr2=cust.addr2 and pa.city=cust.city 
            and pa.state=cust.state and substring(cust.zip,1,5) = pa.zip  )
    left outer join supp_original suppl 
        on (pa.addr1=suppl.addr1 and pa.addr2=suppl.addr2 and pa.city=suppl.city 
                and pa.state=suppl.state and pa.zip = substring(suppl.zip,1,5))
    left outer join partner_original partn
        on (pa.addr1=partn.addr1 and pa.addr2=partn.addr2 and pa.city=partn.city
                  and pa.state=partn.state and pa.zip = substring(partn.zip,1,5) )
where pa.address_id = address_id

作为新手,我无法转换为更新语句,即使用 select 语句返回的值更新现有行。 非常感谢任何帮助。

【问题讨论】:

  • 地址表中是否有任何类型的 id,可用于确定该行是否存在?
  • 是的,但它的系统已生成。

标签: sql postgresql subquery sql-update


【解决方案1】:

有很多方法可以更新行。

当涉及到UPDATE 使用子查询的行时,您可以使用这些方法中的任何一种。

  1. Approach-1 [使用直接表引用]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2>
WHERE
  <table1>.address_id=<table2>.address_i;

解释:table1 是我们要更新的表,table2 是表,我们将从中获取要替换/更新的值。 我们使用FROM 子句来获取table2 的数据。 WHERE 子句将有助于设置正确的数据映射。

  1. 方法 2 [使用子查询]
UPDATE
  <table1>
SET
  customer=subquery.customer,
  address=subquery.address,
  partn=subquery.partn
FROM
  (
    SELECT
      address_id, customer, address, partn
    FROM  /* big hairy SQL */ ...
  ) AS subquery
WHERE
  dummy.address_id=subquery.address_id;

解释:这里我们在FROM子句中使用子查询, 并给它一个别名。这样它就会像桌子一样。

  1. 方法 3 [使用多个联接表]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2> as t2
  JOIN <table3> as t3
  ON
    t2.id = t3.id
WHERE
  <table1>.address_id=<table2>.address_i;

解释:有时我们面临的情况是,表连接是这样的 获取正确的更新数据很重要。为此,Postgres 允许 我们在FROM 子句中加入多个表。

  1. 方法 4 [使用 WITH 语句]
  • 4.1 [使用简单查询]
WITH subquery AS (
    SELECT
      address_id,
      customer,
      address,
      partn
    FROM
      <table1>;
)
UPDATE <table-X>
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE <table-X>.address_id = subquery.address_id;
  • 4.2 [使用复杂 JOIN 查询]
WITH subquery AS (
    SELECT address_id, customer, address, partn
    FROM
      <table1> as t1
    JOIN
      <table2> as t2
    ON
      t1.id = t2.id;
    -- You can build as COMPLEX as this query as per your need.
)
UPDATE <table-X>
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE <table-X>.address_id = subquery.address_id;

说明:从 Postgres 9.1 开始,这个(WITH) 概念已经 介绍。使用它我们可以进行任何复杂的查询并生成 渴望的结果。这里我们使用这种方法来更新表格。

我希望这会有所帮助..?

【讨论】:

  • 很高兴@Mayur 感谢您花时间将所有答案汇总在一起。我个人选择 4 号,因为对我来说它是最易读的(通过分离两个查询)并且最灵活,因为您可以将所需的任何内容放入 WITH
  • 很高兴知道我的回答很有帮助。继续编码:)
【解决方案2】:

您正在使用UPDATE FROM 语法。

UPDATE 
  table T1  
SET 
  column1 = T2.column1 
FROM 
  table T2 
  INNER JOIN table T3 USING (column2) 
WHERE 
  T1.column2 = T2.column2;

参考文献

【讨论】:

    【解决方案3】:

    @Mayur “4.2 [使用复杂 JOIN 查询]”公用表表达式 (CTE)对我有用。

    WITH cte AS (
    SELECT e.id, e.postcode
    FROM employees e
    LEFT JOIN locations lc ON lc.postcode=cte.postcode
    WHERE e.id=1
    )
    UPDATE employee_location SET lat=lc.lat, longitude=lc.longi
    FROM cte
    WHERE employee_location.id=cte.id;
    

    希望这会有所帮助... :D

    【讨论】:

      【解决方案4】:

      如果使用连接没有性能提升,那么我更喜欢公用表表达式 (CTE) 以提高可读性:

      WITH subquery AS (
          SELECT address_id, customer, address, partn
          FROM  /* big hairy SQL */ ...
      )
      UPDATE dummy
      SET customer = subquery.customer,
          address  = subquery.address,
          partn    = subquery.partn
      FROM subquery
      WHERE dummy.address_id = subquery.address_id;
      

      恕我直言,更现代一点。

      【讨论】:

      • 语法与旧版本的 Postgres 不兼容,v9.1 之前,(见postgresql.org/docs/9.1/static/sql-update.html 和以前的版本)我在 v8.2,所以你必须把整个FROM 关键字后括号内的 CTE/With 语句,它将起作用。
      • 这是我到处寻找的。谢谢!
      【解决方案5】:
      update json_source_tabcol as d
      set isnullable = a.is_Nullable
      from information_schema.columns as a 
      where a.table_name =d.table_name 
      and a.table_schema = d.table_schema 
      and a.column_name = d.column_name;
      

      【讨论】:

        【解决方案6】:

        Postgres 允许:

        UPDATE dummy
        SET customer=subquery.customer,
            address=subquery.address,
            partn=subquery.partn
        FROM (SELECT address_id, customer, address, partn
              FROM  /* big hairy SQL */ ...) AS subquery
        WHERE dummy.address_id=subquery.address_id;
        

        这种语法不是标准的 SQL,但是对于这种类型的查询来说,它比标准的 SQL 方便得多。我相信甲骨文(至少)接受类似的东西。

        【讨论】:

        • FWIW,Oracle 确实接受了这种基本结构,但是随着表变大,更新的性能往往会严重下降。没关系。虽然 Oracle 也支持 MERGE 语句。
        • 这在 postgresql 9.5 中完全不起作用,我得到 ERROR: 42P01: relation "dummy" does not exist
        • dummy 必须替换为您尝试更新的表的名称。请在尝试申请之前了解问题和答案。
        • 是的,很抱歉。我的错。没有注意到原来的问题是使用名为“dummy”的表
        • 可能值得一提的是,在查询的开头不必指定左侧列的路径,只需在末尾指定,否则db会报错:列引用“address_id”不明确
        猜你喜欢
        • 1970-01-01
        • 2021-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-24
        • 2017-08-28
        相关资源
        最近更新 更多