更新多行时强制转换 NULL 类型

2023-11-22

当我尝试同时更新多行时遇到问题。

这是我使用的表和查询(为了更好的阅读而进行了简化):

table

CREATE TABLE foo
(
    pkid integer,
    x integer,
    y integer
)

query

UPDATE foo SET x=t.x, y=t.y FROM
(VALUES (50, 50, 1),
        (100, 120, 2))
AS t(x, y, pkid) WHERE foo.pkid=t.pkid

这个查询工作得很好,但是当我尝试执行一个查询时,所有x or y值为空,我收到错误:

带空值的查询

UPDATE foo SET x=t.x, y=t.y FROM
(VALUES (null, 20, 1),
        (null, 50, 2))
AS t(x, y, pkid) WHERE foo.pkid=t.pkid

error

ERROR:  column "x" is of type integer but expression is of type text
LINE 1: UPDATE foo SET x=t.x FROM

解决此问题的唯一方法是更改​​至少一个值(null, 20, 1) to (null:int, 50, 2)但我不能这样做,因为我有一个函数可以生成这些“更新多行”查询,并且它不知道有关列类型的任何信息。

这里最好的解决方案是什么?有没有更好的多行更新查询?有没有类似的函数或语法AS t(x:gettype(foo.x), y:gettype(foo.y), pkid:gettype(foo.pkid))?


带有独立的VALUES表达式 PostgreSQL 不知道数据类型应该是什么。对于简单的数字文字,系统很乐意假设匹配的类型。但对于其他输入(例如NULL)你需要显式地进行转换 - 正如你已经发现的那样。

您可以查询pg_catalog(快速,但特定于 PostgreSQL)或information_schema(缓慢但标准的 SQL)找出并使用适当的类型准备语句。

或者你可以使用这些简单的“技巧”之一(我保存了最好的last):

0. 选择行LIMIT 0,附加行UNION ALL VALUES

UPDATE foo f
SET    x = t.x
     , y = t.y
FROM  (
  (SELECT pkid, x, y FROM foo LIMIT 0) -- parenthesis needed with LIMIT
   UNION ALL
   VALUES
      (1, 20, NULL)  -- no type casts here
    , (2, 50, NULL)
   ) t               -- column names and types are already defined
WHERE  f.pkid = t.pkid;

子查询的第一个子选择:

(SELECT x, y, pkid  FROM foo LIMIT 0)

获取列的名称和类型,但是LIMIT 0阻止它添加实际行。后续行被强制为现在定义良好的行类型 - 并立即检查它们是否与该类型匹配。应该是对原始形式的微妙的额外改进。

在提供价值的同时all表的列此简短语法可用于第一行:

(TABLE foo LIMIT 0)

Major 局限性:Postgres 转换独立的输入文字VALUES立即表达为“尽力而为”类型。当它稍后尝试转换为第一个的给定类型时SELECT,如果假定类型和目标类型之间没有注册的赋值转换,那么对于某些类型来说可能已经太晚了。例子:text -> timestamp or text -> json.

Pro:

  • 最小开销。
  • 可读、简单、快速。
  • 您只需要知道表的相关列名即可。

Con:

  • 对于某些类型,类型解析可能会失败。

1. 选择行LIMIT 0,附加行UNION ALL SELECT

UPDATE foo f
SET    x = t.x
     , y = t.y
FROM  (
  (SELECT pkid, x, y FROM foo LIMIT 0) -- parenthesis needed with LIMIT
   UNION ALL SELECT 1, 20, NULL
   UNION ALL SELECT 2, 50, NULL
   ) t               -- column names and types are already defined
WHERE  f.pkid = t.pkid;

Pro:

  • Like 0.,但避免类型解析失败。

Con:

  • UNION ALL SELECT慢于VALUES正如您在测试中发现的那样,长行列表的表达式。
  • 每行详细语法。

2. VALUES具有每列类型的表达式

...
FROM  (
   VALUES 
     ((SELECT pkid FROM foo LIMIT 0)
    , (SELECT x    FROM foo LIMIT 0)
    , (SELECT y    FROM foo LIMIT 0))  -- get type for each col individually
   , (1, 20, NULL)
   , (2, 50, NULL)
   ) t (pkid, x, y)  -- columns names not defined yet, only types.
...

与之相反0.这可以避免过早的类型解析。

中的第一行VALUES表达式是一行NULL定义所有后续行的类型的值。该主要噪声行被过滤WHERE f.pkid = t.pkid后来,所以它再也见不到天日了。出于其他目的,您可以使用以下命令消除添加的第一行OFFSET 1在子查询中。

Pro:

  • 通常比1.(甚至0.)
  • 具有许多列但只有少数列相关的表的简短语法。
  • 您只需要知道表的相关列名即可。

Con:

  • 仅适用于几行的详细语法
  • 可读性较差(IMO)。

3. VALUES行类型表达式

UPDATE foo f
SET x = (t.r).x         -- parenthesis needed to make syntax unambiguous
  , y = (t.r).y
FROM (
   VALUES
      ('(1,20,)'::foo)  -- columns need to be in default order of table
     ,('(2,50,)')       -- nothing after the last comma for NULL
   ) t (r)              -- column name for row type
WHERE  f.pkid = (t.r).pkid;

您显然知道表名。如果您还知道列数及其顺序,则可以使用它。

对于 PostgreSQL 中的每个表,都会自动注册一个行类型。如果您匹配表达式中的列数,则可以转换为表的行类型('(1,50,)'::foo) 从而隐式分配列类型。逗号后面不加任何内容即可输入NULL价值。为每个不相关的尾随列添加逗号。
在下一步中,您可以使用演示的语法访问各个列。更多关于领域选择在手册中.

或者你可以add一行 NULL 值并对实际数据使用统一语法:

...
  VALUES
      ((NULL::foo))  -- row of NULL values
    , ('(1,20,)')    -- uniform ROW value syntax for all
    , ('(2,50,)')
...

Pro:

  • 最快(至少在我的测试中,行和列很少)。
  • 适用于需要所有列的少数行或表的最短语法。
  • 您不必拼写表的列 - 所有列都会自动具有匹配的名称。

Con:

  • 从记录/行/复合类型中选择字段的语法不太为人所知。
  • 您需要知道默认顺序中相关列的数量和位置。

4. VALUES表达与分解的行类型

Like 3.,但使用标准语法分解行:

UPDATE foo f
SET    x = t.x
     , y = t.y
FROM (
   VALUES
      (('(1,20,)'::foo).*)  -- decomposed row of values
    , (2, 50, NULL)
   ) t(pkid, x, y)  -- arbitrary column names (I made them match)
WHERE  f.pkid = t.pkid;     -- eliminates 1st row with NULL values

或者,再次使用前导行 NULL 值:

...
   VALUES
      ((NULL::foo).*)  -- row of NULL values
    , (1, 20, NULL)    -- uniform syntax for all
    , (2, 50, NULL)
...

优点和缺点 like 3.,但具有更常见的语法。
并且您需要拼写出列名称(如果需要)。

5. VALUES具有从行类型获取的类型的表达式

Like 温里尔评论道,我们可以结合以下优点2. and 4.仅提供列的子集:

UPDATE foo f
SET   (  x,   y)
    = (t.x, t.y)  -- short notation, see below
FROM (
   VALUES
      ((NULL::foo).pkid, (NULL::foo).x, (NULL::foo).y)  -- subset of columns
    , (1, 20, NULL)
    , (2, 50, NULL)
   ) t(pkid, x, y)       -- arbitrary column names (I made them match)
WHERE  f.pkid = t.pkid;

优点和缺点 like 4.,但我们可以使用列的任何子集,而不必知道完整列表。

还显示简短语法UPDATE本身对于有很多列的情况很方便。有关的:

  • 批量更新所有列

4.和5.是我的最爱。

数据库小提琴here- 展示所有

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更新多行时强制转换 NULL 类型 的相关文章

  • 使用sqlbulkcopy之前如何创建表

    我有一个 DBF 文件 我正在尝试导入该文件 然后将其写入 SQL 表 我遇到的问题是 如果我使用 SqlBulkCopy 它需要我提前创建表 但在我的场景中这是不可能的 因为 dbf 文件不断变化 到目前为止 这是我的代码 public
  • SQL 中的代码重用和模块化

    代码重用和模块化对于 SQL 存储过程编程来说是一个好主意吗 如果是这样 将这些功能添加到 SQL 存储过程代码库的最佳方法是什么 我通常为常见且重复的任务创建标量值函数 我发现它不仅可以简化与现有程序类似的新程序的开发 而且还有助于错误跟
  • Postgresql 致命数据库系统正在启动 - Windows 10

    我已经安装了postgresql on windows 10 on usb disk 每天当我启动电脑工作时sleep并再次插入磁盘然后尝试启动postgresql我收到这个错误 FATAL the database system is s
  • 如何获取 JDBC 中 UPDATE 查询影响的所有行?

    我有一项任务需要使用更新记录PreparedStatement 一旦记录被更新 我们知道更新查询返回计数 即受影响的行数 但是 我想要的不是计数 而是受更新查询影响的行作为响应 或者至少是受影响的行的 id 值列表 这是我的更新查询 UPD
  • 向Java类库添加函数

    我使用的 Java 类库在很多方面都不完整 有很多类我认为应该内置其他成员函数 但是 我不确定添加这些成员函数的最佳实践 让我们调用不足的基类A class A public A long arbitrary arguments publi
  • 选择每组最新的项目[重复]

    这个问题在这里已经有答案了 可能的重复 检索每组中的最后一条记录 https stackoverflow com questions 1313120 retrieving the last record in each group 我有 2
  • 从 SQL Server 中的子查询值或其他聚合函数获取平均值

    我有 SQL 语句 SQL Server SELECT COUNT ActionName AS pageCount FROM tbl 22 Benchmark WHERE DATEPART dw CreationDate gt 1 AND
  • MySQL 查询中的窗口函数

    有没有办法在 SELECT 查询本身中动态地使用 MySQL 查询中的窗口函数 我知道在 PostgreSQL 中这是可能的 例如 下面是 PostgreSQL 中的等效查询 SELECT c server ip c client ip s
  • Haskell数据类型转换问题

    我目前正在学习 Haskell 并且一直在编写一些非常简单的程序来练习 我的程序之一是 import System IO main do putStrLn Give me year y lt getLine let res show cal
  • PostgreSQL & regexp_split_to_array + 取消嵌套

    我有这样的绳子 测试1 纽约 X 测试 2 芝加哥 Y 测试 3 宾夕法尼亚州哈里斯堡 Z 我需要的结果是 Column1 Column 2 Column3 Test 1 new york X Test 2 chicago Y Test 3
  • 如何在oracle中获取表作为输出参数

    我正在尝试将 Oracle 过程调用的 out 参数强制转换为对象 它不起作用 因为 据我了解 我需要定义一个映射 它告诉方法如何转换它 如果地图为空或未正确填充 则它默认为 STRUCT 类型的对象 在我的情况下这是错误的 我已经构建了一
  • 严格的别名和内存对齐

    我有性能关键的代码 并且有一个巨大的函数 它在函数开头的堆栈上分配了 40 个不同大小的数组 大多数这些数组必须具有一定的对齐方式 因为这些数组是使用需要内存对齐的 cpu 指令在链下的其他地方访问的 对于 Intel 和 Arm CPU
  • VIEW for 表结合 UNION ALL 的 MySQL 性能

    假设我有 2 张桌子MySQL create table persons id bigint unsigned not null auto increment first name varchar 64 surname varchar 64
  • 在bigquery中比较两个表的有效方法

    我有兴趣比较两个表是否包含相同的数据 我可以这样做 standardSQL SELECT key1 key2 FROM SELECT table1 key1 table1 key2 table1 column1 table2 column1
  • 如何显示 RSpec 测试生成的 SQL 查询日志?

    我正在为我的 Rails 3 应用程序编写规范 我想测试数据库事务是否真的有效 如果能够看到我的应用程序在规范驱动下生成的 sql 查询 这将非常有帮助 有没有办法像在 Rails 控制台中一样查看查询 我正在使用 Rails 3 0 9
  • 尚未为此带有 SQL Server 的 DbContext .NET Core 配置数据库提供程序

    我一直用这个把头撞在墙上 并且一直在谷歌上搜索无济于事 我刚刚开始一个新的 ASP NET Core MVC 项目 我已将这两个包安装 更新为 2 2 0 Microsoft EntityFrameworkCore SqlServer Mi
  • 在 SELECT 中将列值拆分为两列?

    我在 varchar 列中有一个字符串值 它是一个由两部分组成的字符串 在它到达数据库之前分割它不是一个选择 该列的值如下所示 one column part1 part2 part1 part2 所以我想要的是一个如下所示的结果集 col
  • Solr 增量导入不起作用

    我使用的是solr 4 2 请注意 完全导入有效 但增量导入却无效 增量导入不会给出任何错误 但不会获取任何更改 这是数据配置文件
  • SQL Server查询麻烦,多对多关系

    不知道如何用一行字来表达这个问题 对标题表示歉意 我的数据库中有3个表 例如 Shop Item 商店库存 Shop 和 Item 具有多对多关系 因此 ShopStock 表将它们链接起来 ShopStock 中的字段是 ID ShopI
  • Postgresql:SERIAL 在约束 INSERT 失败时递增

    有一个像这样的简单表结构 CREATE TABLE test id INT PRIMARY KEY sid SERIAL 我注意到如果我尝试插入一行但它未通过约束测试 即主键约束 SERIAL计数器无论如何都会增加 所以下一次成功插入 si

随机推荐

  • 使用 httpclient 和 asynctask 取消文件下载

    在我的应用程序中 我需要从 url 位置下载文件 我想在对话框中 或可选地在通知区域中 显示下载进度 我遇到过一些关于这个主题的好资源 比如http progrnotes blogspot com 2010 09 c android htm
  • vscode 语言客户端扩展 - 如何从服务器向客户端发送消息?

    我一直在开发一个 vscode 扩展 它由使用语言服务器协议的客户端和服务器组成 目前 我正在尝试做以下事情 当服务器检测到某种条件时 他请求客户端将一定数量的文件加载到工作区中 我在做这件事时遇到了严重的问题 由于语言服务器协议没有执行此
  • 将稀疏数组中的元素与矩阵中的行相乘

    如果你有一个稀疏矩阵 X gt gt X csr matrix 0 2 0 2 0 2 0 1 gt gt print type X gt gt print X todense
  • 如何使用 java 13 设置 spring-boot 应用程序

    我正在创建一个 spring boot 应用程序 它在 openJdk12 上运行且性能良好 应用程序 https github com jactor rises jactor persistence 我正在寻找如何使用 openJdk13
  • Java MimetypesFileTypeMap 在 Android 模拟器上始终返回 application/octet-stream

    我正在尝试确定 Android 设备 实际上是我与模拟器一起使用的虚拟设备 上存储的文件的 Mime 媒体类型 我找到了这个资源从文件中获取 MIME 类型其中推荐了javax activation MimetypesFileTypeMap
  • 更新到构建工具 2.3.0 后,LibraryPlugin 中没有 sdkHandler 字段

    我正在使用此方法来获取 NDK 目录 project plugins findPlugin com android library sdkHandler getNdkFolder 更新后com android tools build gra
  • 在 iframe 中包含 jQuery 时,Internet Explorer 9(不是早期版本或其他浏览器)中出现错误

    基本上我有一个页面启动了 fancybox iframe 在该 iframe 中我还包含 jQuery 但是当我在 Internet Explorer 9 中测试它时 它给了我错误 行 68 n 错误 对象 未定义 该错误在文件中jquer
  • Python 和 Matlab 中的克罗内克积

    我试图从 MATLAB 中用 Python 重现结果 但是 我似乎无法正确理解 这是正确的 MATLAB 代码 nx 5 ny 7 x linspace 0 1 nx dx x 2 x 1 y linspace 0 1 ny dy y 2
  • Python:在 Windows 上启动新的命令提示符并等待其完成/退出

    我不明白为什么在 Windows 上做到这一点这么难 我想生成一堆命令提示符窗口来运行其他脚本 我想要这个的原因是这样我可以整齐地看到每个脚本的所有输出 如果我将它们只是主窗口中的线程 子进程 我无法正确查看所有输出 我也不想记录输出 因为
  • C# 拖放在 Windows 7 上不起作用

    我有一个使用 C winforms 的项目已经有一段时间了 我在windows 7发布之前就实现了拖放功能 工作起来就像一个魅力 但是 当使用 Windows 7 时 它不起作用 该事件甚至没有被触发 AllowDrop设置为 true 订
  • 无法在 Kafka Stream 应用程序的 IDE 中删除状态目录

    我正在开发一个简单的 Kafka Stream 应用程序 它从一个主题中提取消息并在转换后将其放入另一个主题中 我正在使用 Intelij 进行开发 当我调试 运行这个应用程序时 如果我的 IDE 和 Kafka 服务器位于同一台机器 即
  • 使用 JavaScript 自定义确认对话框

    我想创建一个类似于的 JavaScript 函数confirm 显示一个对话框 一个带有问题和 2 个按钮的 div 并返回true如果用户单击 确定 或false否则 是否可以使用 JavaScript jQuery 做到这一点 但是wi
  • 对绑定在一起的 NSTextField 使用 KVO

    我在使用 KVO 处理 Cocoa 应用程序中绑定在一起的文本字段时遇到问题 当使用按钮在 NSTextFields 中设置字符串时 我已经得到了这个工作 但它不适用于绑定 一如既往 我们将非常感谢 Stack Overflow 提供的任何
  • 以编程方式忽略 Cout

    有谁知道是否有一个技巧可以切换所有cout lt lt 函数不打印可见输出 我正在尝试将我和其他人编写的一些代码组合在一起以制作一个演示 我不想将输出重定向到文件 并且想要一个在 Windows 和 Linux 之间具有一定兼容性的解决方案
  • Node.js / Express 应用程序中的测试环境

    我刚刚开始使用 Node 并且一直在关注各种教程 我创建了一个 Express 应用程序 并设置了 Mongoose 和 Jasmine 我如何配置我的规格 以便我可以 创建模型 在每个规格后自动清理它们 使用不同的数据库来创建测试对象 例
  • Python 来自 Python:限制功能? [复制]

    这个问题在这里已经有答案了 可能的重复 Python 安全 沙箱 我正在用 Python 构建一个企业 Web 系统 该系统允许上传脚本并在服务器端运行 鉴于我已经在使用 Python 进行开发 而且它是一种非常简单的语言 它似乎是一种编写
  • 如何在 Ruby on Rails 中使用映射表跟踪模型历史记录?

    dream 我想记录用户何时更改地址 这样 当下订单时 它将始终能够引用下订单时使用的用户地址 可能的图式 users id username email user addresses id label line 1 line 2 city
  • Agda 的 Haskell 推导机制

    我想知道 Agda 中是否有任何类似于 Haskell 的东西deriving Eq条款 那么我下面还有一个相关的问题 例如 假设我有一种玩具语言的类型 data Type Set where Nat Type Prp Type 然后我可以
  • 有没有办法覆盖 LINQtoSQL 生成的类中的空构造函数?

    如果我的数据库中有一个名为 Users 的表 则 LINQtoSQL 会生成一个名为 User 的类 该类具有已声明的空构造函数 如果我想重写此构造函数并向其中添加我自己的逻辑 最佳实践是什么 由 O R 设计器生成的默认构造函数调用一个名
  • 更新多行时强制转换 NULL 类型

    当我尝试同时更新多行时遇到问题 这是我使用的表和查询 为了更好的阅读而进行了简化 table CREATE TABLE foo pkid integer x integer y integer query UPDATE foo SET x