4

我的任务之一是将访问 SQL 转换为 Oracle SQL。我在MS access中运行了查询,下面是关系表、查询SQL和查询结果: 查询设计

查询结果

访问查询 SQL

SELECT PUBLISHER.PUBLISHER_CODE, PUBLISHER.PUBLISHER_NAME, BOOK.TITLE, BOOK.TYPE, INVENTORY.BRANCH_NUM, BRANCH.BRANCH_NAME
FROM PUBLISHER INNER JOIN (BRANCH INNER JOIN (BOOK INNER JOIN INVENTORY ON BOOK.BOOK_CODE = INVENTORY.BOOK_CODE) ON BRANCH.BRANCH_NUM = INVENTORY.BRANCH_NUM) ON PUBLISHER.PUBLISHER_CODE = BOOK.PUBLISHER_CODE
WHERE (((BOOK.TYPE)='FIC') AND ((BRANCH.BRANCH_NAME)='Henry on the Hill'))
ORDER BY PUBLISHER.PUBLISHER_NAME;

考虑到 MS SQL 可能在 oracle 中工作,我试了一下:

SQL> SELECT PUBLISHER.PUBLISHER_CODE, PUBLISHER.PUBLISHER_NAME, BOOK.TITLE, BOOK.TYPE, INVENTORY.BRANCH_NUM, BRANCH.BRANCH_NAME
  2  FROM PUBLISHER INNER JOIN (BRANCH INNER JOIN (BOOK INNER JOIN INVENTORY ON BOOK.BOOK_CODE = INVENTORY.BOOK_CODE) ON BRANCH.BRANCH_NUM = INVENTORY.BRANCH_NUM) ON PUBLISHER.PUBLISHER_CODE = BOOK.PUBLISHER_CODE
  3  WHERE (((BOOK.TYPE)='FIC') AND ((BRANCH.BRANCH_NAME)='Henry on the Hill'))
  4  ORDER BY PUBLISHER.PUBLISHER_NAME;

no rows selected

显然那没有用。所以,我在我的 oracle 11g 中做了一个剪切/粘贴/编辑的事情。这是我得到的:

SQL> SELECT PUBLISHER.PUBLISHER_CODE, PUBLISHER.PUBLISHER_NAME, BOOK.TITLE, BOOK.TYPE,
  2   INVENTORY.BRANCH_NUM, BRANCH.BRANCH_NAME
  3  FROM PUBLISHER
  4   inner join BOOK  ON PUBLISHER.PUBLISHER_CODE = BOOK.PUBLISHER_CODE
  5  inner join INVENTORY on INVENTORY.BRANCH_NUM = BRANCH.BRANCH_NUM
  6  inner join BRANCH on INVENTORY.BRANCH_NUM = BRANCH.BRANCH_NUM
  7   where BOOK.BOOK_TYPE = 'FIC'
  8   and BRANCH.BRANCH_NAME = 'Henry on the Hill';
inner join INVENTORY on INVENTORY.BRANCH_NUM = BRANCH.BRANCH_NUM
                                               *
ERROR at line 5:
ORA-00904: "BRANCH"."BRANCH_NUM": invalid identifier

那么为什么我会得到这个:第 5 行的错误:ORA-00904:“BRANCH”。“BRANCH_NUM”:无效标识符

连接顺序会影响什么吗?如您所见,我确实按顺序从一张桌子到另一张桌子。

语法顺序重要吗?前任:

INVENTORY.BRANCH_NUM = BRANCH.BRANCH_NUM 上的 内部连接 ​​BRANCH BRANCH.BRANCH_NUM = INVENTORY.BRANCH_NUM 上的内部连接 ​​BRANCH

这有关系吗?

Oracle SQL 中的连接格式是否正确,顺序是否正确?

如果是这样,它为什么不运行?


旁注,这是一门在线课程,虽然讲师很专心,但我从阅读其他人的帖子和提出自己的问题中学到了很多东西。谢谢大家!

4

2 回答 2

2

连接顺序很重要,例如检查这个答案。您不能访问在条件之前没有引入的表别名,例如,您不能BRANCH在第 5 行访问,因为它只在下一个连接中引入。

来自的代码MS Access引入了很多括号来限制连接顺序。只需对其应用格式并查看结果:

SELECT
  PUBLISHER.PUBLISHER_CODE,
  PUBLISHER.PUBLISHER_NAME,
  BOOK.TITLE,
  BOOK.TYPE,
  INVENTORY.BRANCH_NUM,
  BRANCH.BRANCH_NAME
FROM
  PUBLISHER
  INNER JOIN (
    BRANCH INNER JOIN (
      BOOK INNER JOIN INVENTORY
        ON BOOK.BOOK_CODE = INVENTORY.BOOK_CODE
      )
      ON BRANCH.BRANCH_NUM = INVENTORY.BRANCH_NUM
    )
    ON PUBLISHER.PUBLISHER_CODE = BOOK.PUBLISHER_CODE
WHERE
  (
    (
      (BOOK.TYPE)='FIC'
    )
    AND
    (
      (BRANCH.BRANCH_NAME)='Henry on the Hill'
    )
  )
ORDER BY
  PUBLISHER.PUBLISHER_NAME

删除不需要的括号后,如下所示:

SELECT
  PUBLISHER.PUBLISHER_CODE,
  PUBLISHER.PUBLISHER_NAME,
  BOOK.TITLE,
  BOOK.TYPE,
  INVENTORY.BRANCH_NUM,
  BRANCH.BRANCH_NAME
FROM
  PUBLISHER
  INNER JOIN BRANCH
  INNER JOIN BOOK
  INNER JOIN INVENTORY
             ON BOOK.BOOK_CODE = INVENTORY.BOOK_CODE
                AND
                BRANCH.BRANCH_NUM = INVENTORY.BRANCH_NUM
                AND
                PUBLISHER.PUBLISHER_CODE = BOOK.PUBLISHER_CODE
WHERE
  BOOK.TYPE='FIC'
  AND
  (BRANCH.BRANCH_NAME = 'Henry on the Hill')
ORDER BY
  PUBLISHER.PUBLISHER_NAME

看起来更好,但可以通过将 ANSI 语法转换为普通查询来避免排序问题:
警告:ANSI 语法很有趣,请不要阅读此答案的其余部分 :-)

SELECT
  PUBLISHER.PUBLISHER_CODE,
  PUBLISHER.PUBLISHER_NAME,
  BOOK.TITLE,
  BOOK.TYPE,
  INVENTORY.BRANCH_NUM,
  BRANCH.BRANCH_NAME
FROM
  PUBLISHER,
  BRANCH,
  BOOK,
  INVENTORY
WHERE
  BOOK.TYPE='FIC'
  AND
  (BRANCH.BRANCH_NAME = 'Henry on the Hill')
  AND
  PUBLISHER.PUBLISHER_CODE = BOOK.PUBLISHER_CODE
  AND
  BOOK.BOOK_CODE = INVENTORY.BOOK_CODE
  AND
  BRANCH.BRANCH_NUM = INVENTORY.BRANCH_NUM
ORDER BY
  PUBLISHER.PUBLISHER_NAME

使用这种不同的条件顺序无关紧要,所有条件都放在一起,因此可以按逻辑顺序重新组织它:

SELECT
  PUBLISHER.PUBLISHER_CODE,
  PUBLISHER.PUBLISHER_NAME,
  BOOK.TITLE,
  BOOK.TYPE,
  INVENTORY.BRANCH_NUM,
  BRANCH.BRANCH_NAME
FROM
  BRANCH,
  INVENTORY,
  BOOK,
  PUBLISHER
WHERE
  (BRANCH.BRANCH_NAME = 'Henry on the Hill') -- start from most restrictive 
                                             -- condition (concrete branch)  
  AND
  INVENTORY.BRANCH_NUM = BRANCH.BRANCH_NUM   -- get all inventory from this branch
  AND
  BOOK.BOOK_CODE = INVENTORY.BOOK_CODE       -- access book specification 
                                             -- corresponding to inventory
  AND    
  BOOK.TYPE = 'FIC'                          -- of specific type 
  AND
  PUBLISHER.PUBLISHER_CODE = BOOK.PUBLISHER_CODE  -- and finally find 
                                                  -- all publishers of that books
ORDER BY
  PUBLISHER.PUBLISHER_NAME

因此,在最后一个变体中,可以以人类可读的格式重现查询逻辑。
请注意,查询文本中的表顺序(如果您不使用一些特殊提示,至少在 Oracle 中)不会影响真正的查询执行计划,因为优化器会根据需要自行更改它。因此,在大多数情况下,ANSI 变体只是引入了语法限制而没有真正的帮助。

于 2013-10-04T22:58:56.597 回答
1

您的原始查询像这样加入了 INVENTORY:

inner join INVENTORY ON BOOK.BOOK_CODE = INVENTORY.BOOK_CODE

试试这个:

select PUBLISHER.PUBLISHER_CODE, PUBLISHER.PUBLISHER_NAME, BOOK.TITLE, BOOK.TYPE, INVENTORY.BRANCH_NUM, BRANCH.BRANCH_NAME
from PUBLISHER
inner join BOOK on PUBLISHER.PUBLISHER_CODE = BOOK.PUBLISHER_CODE
inner join INVENTORY on BOOK.BOOK_CODE = INVENTORY.BOOK_CODE
inner join BRANCH on BRANCH.BRANCH_NUM = INVENTORY.BRANCH_NUM
where BOOK.TYPE = 'FIC'
    and BRANCH.BRANCH_NAME = 'Henry on the Hill'
order by PUBLISHER.PUBLISHER_NAME;
于 2013-10-04T21:18:09.773 回答