SQL 异常在嵌套查询中使用“USING”子句?

Posted

技术标签:

【中文标题】SQL 异常在嵌套查询中使用“USING”子句?【英文标题】:SQL Anomaly Using 'USING' Clause with Nested Queries? 【发布时间】:2013-04-16 22:41:35 【问题描述】:

我有一个规范化的数据库,其中包含 3 个表,其 DDL 如下:

CREATE CACHED TABLE Clients ( 
    cli_id       INTEGER       GENERATED ALWAYS AS IDENTITY (START WITH 100) PRIMARY KEY,
    defmrn_id    BIGINT,
    lastName     VARCHAR(48)   DEFAULT '' NOT NULL,
    midName      VARCHAR(24)   DEFAULT '' NOT NULL,
    firstName    VARCHAR(24)   DEFAULT '' NOT NULL,
    doB          INTEGER       DEFAULT 0 NOT NULL,
    gender       VARCHAR(1)    NOT NULL);

CREATE TABLE Client_MRNs (
    mrn_id       BIGINT        GENERATED ALWAYS AS IDENTITY (START WITH 100) PRIMARY KEY,
    cli_id       INTEGER       REFERENCES Clients ( cli_id ),
    inst_id      INTEGER       REFERENCES Institutions ( inst_id ),
    mrn          VARCHAR(32)   DEFAULT '' NOT NULL,

    CONSTRAINT climrn01 UNIQUE (mrn, inst_id));

CREATE TABLE Institutions ( 
    inst_id      INTEGER       GENERATED ALWAYS AS IDENTITY (START WITH 100) PRIMARY KEY,
    loc_id       INTEGER       REFERENCES Locales (loc_id ),
    itag         VARCHAR(6)    UNIQUE NOT NULL,
    iname        VARCHAR(80)   DEFAULT '' NOT NULL);

第一个表包含一个外键列 defmrn_id,它是对存储在第二个表中的“默认标识符代码”的引用(它是所有标识符代码的列表)。第一个表中的一条记录可能有很多标识符,但只有一个默认标识符。所以是的,我创建了一个循环引用。

第三个表只是来自第二个表的标准化数据。

我想要一个查询,该查询将基于将提供的标识符代码与可能属于该 CLIENT 记录的 CLIENT_MRN 中的任何标识符代码匹配来查找 CLIENT 记录。

我的策略是首先识别在第二个表 (CLIENT_MRN) 中匹配的那些记录,然后使用该中间结果连接到 CLIENT 表中与其他用户提供的搜索条件匹配的记录。我还需要对第一个表中的标识符引用 defmrn_id 进行非规范化。这是我想出的......

SQL = SELECT c.*, r.mrn, i.inst_id, i.itag, i.iname 
FROM Clients AS c 
INNER JOIN 
  (   
      SELECT m.cli_id   
      FROM Client_MRNs AS m   
      WHERE m.mrn = ? 
  ) AS m2 ON m2.cli_id = c.cli_id 
INNER JOIN Client_MRNs AS r ON c.defmrn_id = r.mrn_id 
INNER JOIN Institutions AS i USING ( inst_id )  
WHERE (<other user supplied search criteria...>);

上述方法有效,但我花了一些时间试图理解为什么以下方法不起作用......

SQL = SELECT c.*, r.mrn, i.inst_id, i.itag, i.iname 
FROM Clients AS c 
INNER JOIN 
  (   
      SELECT m.cli_id   
      FROM Client_MRNs AS m   
      WHERE m.mrn = ? 
  ) AS m2  USING ( cli_id ) 
INNER JOIN Client_MRNs AS r ON c.defmrn_id = r.mrn_id 
INNER JOIN Institutions AS i USING ( inst_id )  
WHERE (<other user supplied search criteria...>);

在我看来,第二个 SQL 应该可以工作,但每次都在 USING 子句上失败。我正在对由 HSQLDB 2.2.9 作为 RDBMS 管理的数据库执行这些查询。这是 HSQLDB 中的解析问题还是嵌套查询的 USING 子句的已知限制?

【问题讨论】:

并非每个 RDBMS 都支持 using 关键字。如果您使用该词在两个表之间进行非常简单的连接,它会执行还是崩溃? HSQLDB 为 USING 谓词提供开箱即用的支持。在第二个 SQL 中,有两个 USING 谓词。第一个失败,但第二个(也出现在工作 SQL 中)的工作方式与预期的一样。 【参考方案1】:

您始终可以尝试使用 HSQLDB 2.3.0(一个候选版本)。

您报告不完整 SQL 的方式不允许正确检查。但是查询中有一个明显的错误。如果你有:

SELECT INST_ID FROM CLIENTS_MRS AS R INNER JOIN INSTITUTIONS AS I USING (INST_ID)

INST_ID 只能在没有表限定符的情况下用于 SELECT 列列表。原因是它不再被视为任一表的列。如果您使用 NATURAL JOIN,公共列也是如此。

2.3.0 版接受此查询

SELECT c.*, r.mrn, inst_id, i.itag, i.iname 
FROM Clients AS c 
INNER JOIN 
  (   
      SELECT m.cli_id   
      FROM Client_MRNs AS m   
      WHERE m.mrn = 2 
  ) AS m2  USING ( cli_id ) 
INNER JOIN Client_MRNs AS r ON c.defmrn_id = r.mrn_id 
INNER JOIN Institutions AS i USING ( inst_id )  

【讨论】:

fred,感谢您抽出宝贵时间回复。抱歉没有更具体。第二条 SQL 报告的错误消息是“错误:用户缺少权限或找不到对象:CLI_ID \n SQL 状态:42501 \n 错误代码:-5501。我知道“使用列”没有 get在结果集元数据中命名值......但是当我以这种方式命名它们时它们仍然显示在我的结果集中。我需要我的 java 端数据模型中的键,所以我一直在使用它。我听说你说我不应该用表名来限定它们。 是的,对于 USING 中的共享列,选择列表中不应允许使用限定名称。 我应该澄清一下,即使我更正列列表以使“i.inst_id”变为“inst_id”,第二个 SQL 在第一个 USING 谓词处继续失败(相同的错误消息),而第一个 SQL 继续像以前一样工作。 请尝试2.3.0版本 我很尴尬地承认,虽然我非常想尝试发布候选版本,但我不喜欢使用 Maven 或快照存储库,即使在浏览了 HSQLDB 用户部分关于使用快照和咨询 NetBeans 的 Maven 支持文档......我仍然缺乏。这个周末我会投入更多的精力。我渴望尝试 2.3.0。

以上是关于SQL 异常在嵌套查询中使用“USING”子句?的主要内容,如果未能解决你的问题,请参考以下文章

SQL相关子查询和嵌套子查询的区别

子查询(嵌套子查询)

在sql中对不相关嵌套查询的处理原则

sql语句中where条件的嵌套子查询性能

求SQL相关子查询和嵌套子查询通俗的区别 ?

ClickHouse高级数据查询SQL: WITH/JOIN/IN/INTO OUTFILE/嵌套子查询/交并差计算等