【问题标题】:Copying a column of data from one table to another in PostgreSQL在 PostgreSQL 中将一列数据从一个表复制到另一个表
【发布时间】:2012-12-06 11:32:17
【问题描述】:

我有以下设置:

表1:

latdouble
3
4
5
1
6
2
6
9

表2:

time    latdouble(type double)    latvarchar(type varchar)   
2:00                              3
3:00                              4
4:00                              5
5:00                              1
6:00                              6
7:00                              2
8:00                              6
9:00                              9

Table1 中的 latdouble 基本上是正确的顺序,我想将这些值原样复制到 Table2 中,结果应该是:

表2:

time    latdouble(type double)    latvarchar(type varchar)   
2:00    3                         3
3:00    4                         4
4:00    5                         5
5:00    1                         1
6:00    6                         6
7:00    2                         2
8:00    6                         6
9:00    9                         9

据我所知,我需要使用类似于以下的命令:

update Table2 set latdouble = (select latdouble from Table1)

但是我收到以下错误:

ERROR: more than one row returned by a subquery used as an expression

我确定有一个简单的解决方法,但我想不通,

谢谢, 詹姆斯

更新:让我解释一下这是怎么发生的。表 2 最初看起来像:

表2:

time    latvarchar(type varchar)   
2:00    3                         
3:00    4                         
4:00    5                         
5:00    1                         
6:00    6                         
7:00    2                         
8:00    6                         
9:00    9

我在 Table2 中添加了 latdouble(type double) 列。

然后我创建了一个名为 Table1 的新表,其中包含一个名为 latdouble(type double) 的列。我使用以下命令从 Table2 中转换 latvarchar 并将其复制到 Table1 中:

insert into Table1 (latdouble) select cast(latvarchar as double precision) from Table2

现在我想将值从 Table1 latdouble 复制回 Table2 latdouble。我这样做的原因是将 latvarchar 中的值转换为 double 并将它们保存在 latdouble 中,而不必创建整个 Table2 的临时副本,因为它是一个带有几个索引的非常大的表。

【问题讨论】:

  • Table1 是否有可排序的主键?如果不是,那么您看到的“订单”只是引擎方面的便利。没有什么可以阻止它在以后的查询中以任何随机顺序显示它...向 Table1 添加并填充一些列以指示您想要的排序顺序,此时将有可能找到解决方案。
  • 不,它没有主键,但请你看看我添加的更新,它解释了这种情况是如何发生的。我选择创建 Table1 的方法是否意味着“订单”不仅仅是方便?
  • 没有主键的表是(接近)没有意义的。
  • 它应该是一个临时表,因此我没有看到需要任何键,但显然如果我添加一个主键,我可以使用它将数据复制到基于表 1在钥匙上。

标签: sql sql-update


【解决方案1】:

如果我理解正确,则根本不需要使用 Table1。您可以使用 UPDATE 为每一行简单地设置 latdouble 值:

UPDATE Table2 SET latdouble = cast(latvarchar as double precision);

更新

要逐步做到这一点,我可以想到 2 个选项。

选项 1.(又快又脏)

UPDATE Table2 
SET latdouble = cast(latvarchar as double precision)
WHERE tKey IN (SELECT tKey FROM Table2 WHERE latdouble IS NULL LIMIT 10000);

多次运行,直到不再更新任何行(这意味着没有 latdouble 字段为 NULL)

选项 2.(使用光标并逐步提交)

按照this article中的方法,就可以运行这个python脚本了:

#!/home/postgres/python/bin/python
#
# incremental commits
# 2008 kcg

import psycopg2
import time

# vars
incremental_commit_size=10000   # number of rows
throttle_time=0         # seconds

connectstr="host=localhost dbname=postgres user=postgres port=5432"
handle=psycopg2.connect(connectstr)
cursor=handle.cursor()
cursor2=handle.cursor()
sql="select tKey from table2"
cursor.execute(sql)

while 1:

 output = cursor.fetchmany(incremental_commit_size)

 if not output:
  break
 for row in output:

   # update table
   sql="update table2 set latdouble = cast(latvarchar as double precision) where tKey = %s"
   cursor2.execute(sql,([row[0]]))

 #commit, invoked every incremental commit size
 handle.commit()
 time.sleep(throttle_time)

handle.commit()

【讨论】:

  • 谢谢,但这不会在 PostgreSQL 中创建 Table2 的临时副本吗?在这种情况下,临时表将占用另外 100GB...
  • 不,它根本不会创建任何临时的东西。它只是用新值更新现有行。你有具体的理由不相信吗?在使用简单的 UPDATE 语句时,我从来没有遇到过这样的问题......
  • 为了强调这一点——如果latdouble 已经作为double precision 存在于您的Table2 中,那么数据库已经为其分配了必要的空间。因此,本专栏的更新根本不应该使您的数据库增长。它当然不需要任何临时表(除了在您使用的任何语句中都无法避免的事务级别)。
  • 是的,我在同一张表上运行了类似的更新命令(不能确定它们是否完全相同)来尝试解决这个问题,但我一直收到空间不足的错误。因此,我在互联网上进行了研究,并阅读了有关更新创建表的临时副本的信息,然后在提交更改并删除临时表之前应用更改。
  • 您可以发布指向此信息的链接吗?这对我来说听起来不正确,但你永远不知道......
猜你喜欢
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 2017-06-03
  • 2017-03-28
  • 1970-01-01
  • 2010-10-05
相关资源
最近更新 更多