【问题标题】:Oracle DB quote column namesOracle DB 引用列名
【发布时间】:2021-05-13 18:09:31
【问题描述】:

使用常规表时,可以使用以下 Oracle SQL 查询:

SELECT max(some_primary_key) FROM MyTable

但是,当使用数据库对象(即对象的表)时,会产生以下错误:

ORA-00904: "SOME_PRIMARY_KEY": invalid identifier

引用列名时,如下所示:

SELECT max("some_primary_key") FROM MyTable

这按预期工作。 为什么在使用对象时需要转义列名,而不是使用表?

【问题讨论】:

标签: sql oracle


【解决方案1】:

它与对象或表格无关,它与这些对象/表格的创建方式有关。

如果你这样做 create table "blabla" 那么你总是需要用“blabla”来寻址这个表,如果你这样做 create table blabla 那么你可以通过 BLABLA 或 blabla 或 bLabLa 来寻址这个表。使用" " 会使名称区分大小写,这就是大多数开发人员不使用" " 的原因,因为通常您不需要区分大小写的名称。

【讨论】:

  • 谢谢,现在这更有意义了 :)
【解决方案2】:

数据库对象命名规则

每个数据库对象都有一个名称。在 SQL 语句中,您表示 带有带引号的标识符或不带引号的对象的名称 标识符。

  • 带引号的标识符以双引号 (") 开头和结尾。如果您使用带引号的标识符命名架构对象,那么您 引用该对象时必须使用双引号。
  • 未加引号的标识符不被任何标点符号包围。

您可以使用带引号或不带引号的标识符来命名任何 数据库对象。但是,数据库名称、全局数据库名称和 数据库链接名称始终不区分大小写并存储为 大写。如果您将此类名称指定为带引号的标识符,则 引号被默默地忽略。请参阅创建用户 命名用户和密码的附加规则。

总结一下

当你这样做时:

SELECT max(some_primary_key) FROM MyTable

Oracle 假设您的列是这样声明的:

CREATE TABLE MyTable (
    some_primary_key INT,
    ...
)

看到产生的错误,事实并非如此。你显然是这样声明的:

CREATE TABLE MyTable (
    "some_primary_key" INT,
    ...
)

因此,您应该始终使用双引号和正确的大小写来引用该列,因此:

SELECT max("some_primary_key") FROM MyTable

圣经:Oracle Database Object Names and Qualifiers

【讨论】:

    【解决方案3】:

    [TL;DR] 最简单的做法是永远不要在对象名称周围使用双引号,而让 oracle 以默认方式管理区分大小写。

    默认情况下,Oracle 数据库区分大小写;但是,默认情况下,它们也会将所有内容都转换为大写,以便从您(用户)那里抽象出区分大小写。

    CREATE TABLE Test ( column_name NUMBER );
    

    然后:

    SELECT COUNT(column_name) FROM test;
    SELECT COUNT(Column_Name) FROM Test;
    SELECT COUNT(COLUMN_NAME) FROM TEST;
    SELECT COUNT(CoLuMn_NaMe) FROM tEsT;
    SELECT COUNT("COLUMN_NAME") FROM "TEST";
    

    都会给出相同的输出并且:

    DESCRIBE test;
    

    输出:

    Name        Null Type
    ----------- ---- ------
    COLUMN_NAME      NUMBER
    

    (注意:Oracle 的默认行为是将名称转换为大写。)

    如果您使用双引号,那么 oracle 将尊重您在对象名称中使用大小写(然后您需要始终使用相同的大小写):

    CREATE TABLE "tEsT" ( "CoLuMn_NaMe" NUMBER );
    

    (注意:表名和列名都用双引号括起来,现在要求您在引用它们时使用完全相同的大小写和引号。)

    那么你只能这样做(因为你需要尊重区分大小写):

    SELECT COUNT("CoLuMn_NaMe") FROM "tEsT";
    

    DESCRIBE "tEsT";
    

    输出:

    Name        Null Type
    ----------- ---- ------
    CoLuMn_NaMe      NUMBER
    

    (注意:Oracle 尊重区分大小写。)

    【讨论】:

    • 不幸的是,我的一些列被命名为at,因此需要对其进行转义(我没有机会更改它们的名称)
    • @tobspr 对此的正常反应是追捕做出该决定的开发人员,并(大力)告知他们在对象名称中使用关键字和/或引号是不好的做法,请他们不要以后再做……除此之外,除了继续使用预期的情况之外,您无能为力。
    • 这是几十年前的遗留代码,很难改变
    【解决方案4】:

    我在 Oracle 11g 中创建了一个对象:

    CREATE OR REPLACE TYPE MyType AS OBJECT (
       some_property NUMBER(20),
      CONSTRUCTOR FUNCTION MyType(some_property number default 123) RETURN SELF AS RESULT
    ) NOT FINAL;
    /
    
    CREATE OR REPLACE TYPE BODY MyType AS
      CONSTRUCTOR FUNCTION MyType(some_property number default 123)
        RETURN SELF AS RESULT
      AS
      BEGIN
        SELF.some_property := some_property;
        RETURN;
      END;
    END;
    /
    

    ---创建了我的对象的表

    CREATE TABLE MYTABLE OF MYTYPE ;
    

    ---发表声明。

    SELECT max(some_property) FROM MYTABLE;
    

    没有引号对我来说工作正常。不知道为什么它不适用于您的情况。你的 oracle 版本是什么?

    【讨论】:

    • 正如@RayCw 提到的,问题是我用引号创建属性,例如"some_property" NUMBER(20),
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 2018-08-20
    • 1970-01-01
    相关资源
    最近更新 更多