When using regular tables, its fine to use the following Oracle SQL query:
SELECT max(some_primary_key) FROM MyTable
However, when using Database Objects (i.e. a table of an object), this yields to the following error:
ORA-00904: "SOME_PRIMARY_KEY": invalid identifier
When quoting the column name, like this:
SELECT max("some_primary_key") FROM MyTable
This works like expected. Why is it necessary to escape column names when working with Objects, but not with Tables?
It doesn't have to do with objects or tables, it has to do with how these objects/tables have been created.
If you do
create table "blabla" then you always need to address this table with "blabla", if you do create table blabla then you can address this table via BLABLA or blabla or bLabLa. Using " " makes the name case sensitive and that is the reason why most developers don't use " " because usually you don't want case sensitive names .
Database Object Naming Rules
Every database object has a name. In a SQL statement, you represent
the name of an object with a quoted identifier or a nonquoted
identifier.
A quoted identifier begins and ends with double quotation marks ("). If you name a schema object using a quoted identifier, then you
must use the double quotation marks whenever you refer to that object.
A nonquoted identifier is not surrounded by any punctuation.
You can use either quoted or nonquoted identifiers to name any
database object. However, database names, global database names, and
database link names are always case insensitive and are stored as
uppercase. If you specify such names as quoted identifiers, then the
quotation marks are silently ignored. Refer to CREATE USER for
additional rules for naming users and passwords.
To summarize this
When you do :
SELECT max(some_primary_key) FROM MyTable
Oracle assume that your column was declared like this :
CREATE TABLE MyTable (
some_primary_key INT,
...
)
Seing the resulting error, it's not the case. You obviously declared it like this :
CREATE TABLE MyTable (
"some_primary_key" INT,
...
)
And you should thus always refer to that column using double quotes and proper case, thus :
SELECT max("some_primary_key") FROM MyTable
The bible : Oracle Database Object Names and Qualifiers
[TL;DR] The simplest thing to do is to never use double quotes around object names and just let oracle manage the case-sensitivity in its default manner.
Oracle databases are, by default, case sensitive; however, they will also, by default, convert everything to upper-case so that the case sensitivity is abstracted from you, the user.
CREATE TABLE Test ( column_name NUMBER );
Then:
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";
Will all give the same output and:
DESCRIBE test;
Outputs:
Name Null Type
----------- ---- ------
COLUMN_NAME NUMBER
(Note: Oracle's default behaviour is to convert the name to upper case.)
If you use double quotes then oracle will respect your use of case in the object's name (and you are then required to always use the same case):
CREATE TABLE "tEsT" ( "CoLuMn_NaMe" NUMBER );
(Note: Both the table and column name are surrounded in double quotes and now require you to use exactly the same case, and quotes, when you refer to them.)
Then you can only do (since you need to respect the case sensitivity):
SELECT COUNT("CoLuMn_NaMe") FROM "tEsT";
And
DESCRIBE "tEsT";
Outputs:
Name Null Type
----------- ---- ------
CoLuMn_NaMe NUMBER
(Note: Oracle has respected the case sensitivity.)
I created one object in 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;
/
---Created a table of my object
CREATE TABLE MYTABLE OF MYTYPE ;
---issued the statement.
SELECT max(some_property) FROM MYTABLE;
Its working fine for me without quotes. Not sure why its not working in your case. Whats your oracle version ?
Related
When I create a table with SQL Developer my columns and the name of the table must be capitalized. I want to use lower case but I don't know how to do it.
This is not something that SQL Developer does; it is done by the Oracle database and is the default behaviour.
From Oracle's Database Object Names and Qualifiers documentation:
Database Object Naming Rules
Every database object has a name. In a SQL statement, you represent the name of an object with a quoted identifier or a nonquoted identifier.
A quoted identifier begins and ends with double quotation marks ("). If you name a schema object using a quoted identifier, then you must use the double quotation marks whenever you refer to that object.
A nonquoted identifier is not surrounded by any punctuation.
You can use either quoted or nonquoted identifiers to name any database object.
...
Nonquoted identifiers are not case sensitive. Oracle interprets them as uppercase. Quoted identifiers are case sensitive.
Which means that if you create any identifier then Oracle will convert it upper-case to store it in the data dictionary and this is the way Oracle is designed to behave.
So:
CREATE TABLE table_name (
id INT PRIMARY KEY
);
Then if you look in the data dictionary:
SELECT table_name, column_name
FROM user_tab_columns;
Then the output is:
TABLE_NAME | COLUMN_NAME
:--------- | :----------
TABLE_NAME | ID
And you could do:
SELECT id FROM table_name;
SELECT ID FROM TABLE_NAME;
SELECT Id FROM TaBlE_nAmE;
SELECT "ID" FROM "TABLE_NAME";
and they would all select from that table as Oracle will implicitly convert the unquoted identifiers to upper-case.
If you quote the identifiers then Oracle will keep those identifiers in the same case as you type them but you will need to ALWAYS quote them whenever your refer to that identifier.
If you do:
CREATE TABLE "table_name" (
"id" INT PRIMARY KEY
);
Then the data dictionary would now contain two tables, one upper case and one lower case:
SELECT table_name, column_name
FROM user_tab_columns;
TABLE_NAME | COLUMN_NAME
:--------- | :----------
TABLE_NAME | ID
table_name | id
and to get data from that second table you would have to use quoted identifiers with the correct case:
SELECT "id" FROM "table_name";
db<>fiddle here
You either quote the identifiers (everywhere they are used) and can have lower-case identifiers or Oracle will implicitly convert the unquoted identifiers to upper-case.
Make things simple for yourself and, if you are manually writing SQL queries, just use unquoted identifiers and accept that behind the scenes Oracle will implicitly convert the case and that that is not a bad thing.
We have Oracle table having default keyword(i.e in as field name) field name.Now i am querying table but unable to extract specific field data.
select a.filename,a.in from table a
Following error appears "invalid field name.
Try using double quotes.
select a."IN" from table a
You can use default (oracle reserved) keywords as the name of the columns but yes it is not advisable to use it.
Anyway, If you want to use oracle reserved keywords then you must have to enclose them in the double-quotes.
Note that oracle is case insensitive in terms of its object names until and unless it is wrapped in the double-quotes. it means if you enclose any object name in double-quotes then you must have to use them anywhere in the entire DB as case sensitive manner.
So if your table definition is:
CREATE TABLE YOUR_TABLE ("IN" NUMBER);
Then you need to use "IN" wherever you want to refer the column but if your table definition is:
CREATE TABLE YOUR_TABLE ("in" NUMBER);
Then you need to use "in" wherever you want to refer the column. -- case sensitive names.
I hope it will clear all your doubts.
Cheers!!
I have a table in which a column name begins with a wildcard. So one of the column is named _Test_
How can I access this column?
select _TEST_ from Table
throws an error, as well as
select *
from Table
where _TEST_ = 123
I tried suggestions with "escape", using [_TEST_], or \_TEST\_ but nothing worked. I cannot change the table.
EDIT (Thanks to #Alex Poole) : select * from Table Where "_TEST_"=123 works. But select "_TEST_" from Table does not.
An underscore is only a wildcard for the like pattern-matching condition. In the context you are trying to use it, it is not a wildcard. The column name just contains an underscore.
The documenation on Database Object Names and Qualifiers shows the rules for object names, including rule 6:
Nonquoted identifiers must begin with an alphabetic character from your database character set. Quoted identifiers can begin with any character.
As your column name starts with an underscore, the column must have been defined with a quoted identifier when the table was created, e.g.:
create table your_table (test number, "_Test_" number);
You can see the exact name for each column in the data dictionary:
COLUMN_NAME
------------------------------
TEST
_Test_
If a column (or any object) follows the non-quoted-identifier rules then it is recorded in uppercase in the data dictionary, but you can refer to it without quotes and with any case; so any of these are valid:
select * from your_table where TEST = 123;
select * from your_table where Test = 123;
select * from your_table where test = 123;
select * from your_table where tEsT = 123;
But if for a quoted identifier you always have to uses quotes and exactly the same case when referring to it. So these error:
select * from your_table where _TEST_ = 123;
select * from your_table where _Test_ = 123;
select * from your_table where "_TEST_" = 123;
(the first two with ORA-00911: invalid character, the third with ORA-00904: "_TEST_": invalid identifier because of the case difference). You have to match exactly, so only this is valid:
select * from your_table where "_Test_" = 123;
This is why quoted identifiers are a pain to work with and should be avoided if possible. Oracle even advise against using them.
I have created a table in Oracle 10g using the following CREATE statement.
CREATE TABLE test ("id" NUMBER(35, 0) primary key, "description" VARCHAR2(250) not null);
The basic table structure looks like as follows.
--------------------------------------------------------------------------------
Column Name Data Type Nullable Default Primary Key
--------------------------------------------------------------------------------
id NUMBER(35, 0) No - 1
description VARCHAR2(250) No - -
It should precisely be noted that the column names in this CREATE statement are enclosed within double quotes just for having a fun :)
After issuing this DDL statement, I issued three DML statements to add this many rows as follows.
INSERT INTO test VALUES (1, 'aaa');
INSERT INTO test VALUES (2, 'bbb');
INSERT INTO test VALUES (3, 'ccc');
And finally, the following SELECT statement was executed to verify, if those rows were inserted.
SELECT * FROM test;
Oracle indeed displays three rows exactly as inserted on executing this query.
But when I issue the following SELECT query,
SELECT id, description FROM test;
Oracle complains,
ORA-00904: "DESCRIPTION": invalid identifier
The following (same) query also,
SELECT id FROM test;
fails with the error,
ORA-00904: "ID": invalid identifier
The same is true for the query,
SELECT description FROM test;
The only SELECT query with the meta character * works. Listing fields in the SELECT clause doesn't work. Capitalizing the column names in the SELECT clause also doesn't work.
What is the reason behind it?
Please don't just say, Don't do this. I'm interested in knowing the reason behind it.
OK, I won't say it, I'll just think it loudly.
The documentation clearly says that if you have quoted identifiers, you have to quote them everywhere (my italics for emphasis):
Every database object has a name. In a SQL statement, you represent the name of an object with a quoted identifier or a nonquoted identifier.
A quoted identifier begins and ends with double quotation marks ("). If you name a schema object using a quoted identifier, then you must use the double quotation marks whenever you refer to that object.
A nonquoted identifier is not surrounded by any punctuation.
So you always have to do:
SELECT "id", "description" FROM test;
Which is a pain. But obviously I'm just thinking that too, not really saying it.
I have a db table say, persons in Postgres handed down by another team that has a column name say, "first_Name". Now am trying to use PG commander to query this table on this column-name.
select * from persons where first_Name="xyz";
And it just returns
ERROR: column "first_Name" does not exist
Not sure if I am doing something silly or is there a workaround to this problem that I am missing?
Identifiers (including column names) that are not double-quoted are folded to lowercase in PostgreSQL. Column names that were created with double-quotes and thereby retained uppercase letters (and/or other syntax violations) have to be double-quoted for the rest of their life:
"first_Name"
Values (string literals / constants) are enclosed in single quotes:
'xyz'
So, yes, PostgreSQL column names are case-sensitive (when double-quoted):
SELECT * FROM persons WHERE "first_Name" = 'xyz';
Read the manual on identifiers here.
My standing advice is to use legal, lower-case names exclusively so double-quoting is never required.
To quote the documentation:
Key words and unquoted identifiers are case insensitive. Therefore:
UPDATE MY_TABLE SET A = 5;
can equivalently be written as:
uPDaTE my_TabLE SeT a = 5;
You could also write it using quoted identifiers:
UPDATE "my_table" SET "a" = 5;
Quoting an identifier makes it case-sensitive, whereas unquoted names are always folded to lower case (unlike the SQL standard where unquoted names are folded to upper case). For example, the identifiers FOO, foo, and "foo" are considered the same by PostgreSQL, but "Foo" and "FOO" are different from these three and each other.
If you want to write portable applications you are advised to always quote a particular name or never quote it.
The column names which are mixed case or uppercase have to be double quoted in PostgresQL. So best convention will be to follow all small case with underscore.
if use JPA I recommend change to lowercase schema, table and column names, you can use next intructions for help you:
select
psat.schemaname,
psat.relname,
pa.attname,
psat.relid
from
pg_catalog.pg_stat_all_tables psat,
pg_catalog.pg_attribute pa
where
psat.relid = pa.attrelid
change schema name:
ALTER SCHEMA "XXXXX" RENAME TO xxxxx;
change table names:
ALTER TABLE xxxxx."AAAAA" RENAME TO aaaaa;
change column names:
ALTER TABLE xxxxx.aaaaa RENAME COLUMN "CCCCC" TO ccccc;
You can try this example for table and column naming in capital letters. (postgresql)
//Sql;
create table "Test"
(
"ID" integer,
"NAME" varchar(255)
)
//C#
string sqlCommand = $#"create table ""TestTable"" (
""ID"" integer GENERATED BY DEFAULT AS IDENTITY primary key,
""ExampleProperty"" boolean,
""ColumnName"" varchar(255))";