Column names using Oracle reserved word - sql

Inside my database I have some tables that use a column with a reserved word name for example user, I have created it using " as "USER" but when I want to get it I have realized that I have to put it in capital letters, I have already investigated and I obtained that when placing " oracle respects it as case sensitive, they somehow know how to avoid this and obtain my column without the need for it to be written as defined, that is, case insensitive.
I am working Oracle with Firedac, on the Firedac side, do you know if something can be done so that this can be solved by having to put the column name as it is?

No.
You chose to have a column that conflicts with a reserved word, so you had to quote it when you declared it. You also need to quote this identifier everytime you use it - and a quoted identifier is case-sensitive by design.
I would strongly suggest avoiding having column names that conflict with SQL reserved word (or keywords). There is no benefit, and many drawbacks. You could just rename that column to usr, username, userid, or else. Declare the new name as a unquoted identifier, and you will never need to worry about this all afterwards.

Related

sp_rename and reserved words

I need to rename a table to CASE which is a reserved word. WHen using delimiters such as [] , I get the name [CASE], which is not my intent. The obvious answer here is to not use the reserved word as a name, however , I am a contractor on a project and don't know what all I will break by changing the name.
As mentioned in the comments, using a reserved keyword for a table name is not a good idea.
Doing so would require every query that refers to the table to use brackets. The query becomes more complex to read, writing a query against that table becomes more error prone, etc...
More to the point, you can save all that trouble if you find a name that isn't a reserved keyword. This simple solution has no drawback and will save headaches in the future.

To make entire column names in lower case in oracle

I am using oracle xe,while creating columns it is created in upper case.Is there any rule to make the entire database columns in lower case.
To answer to your specific question: No
(you cannot globally change all column headings to lowercase)
Nonquoted Identifiers:
Unless you use quotes when creating objects the default for storage is upper case and these are called nonquoted identifiers in documentation. This allows "case insensitive" use of those names. e.g. a field stored with the name DESCRIPTION can be used in lowercase or mixed case like dEscRipTion
Quoted Identifiers
If however you use "quoted identifiers" then you create case sensitive names and all references to them must be a precise match. So a field with the stored name of DesCripTion must always be used with exactly that mixed case and DescripTion would not work.
In short, don't mess with the defaults, you are way better off leaving them as "nonquoted identifiers"
see: Schema Object Naming Rules
use oracle "rename" syntax.
for example:
// existing column on TABLE1 is CITY_NAME
// new name is cityName
// you can rename table and/or columns
rename table SCHEMA1.TABLE1 to "NewTableName"
and
rename column SCHEMA1.TABLE1.CITY_NAME to "cityName"
the main thing to remember is to enclose the new name in quotes.
you have to modify your exiting views and cursors because they will break.

H2 database column name "GROUP" is a reserved word

How do I create a table in H2 with a column named GROUP? I saw an example that used something like [*] a while ago, but I can't seem to find it.
Trailing Underscore
Add a trailing underscore: GROUP_
The SQL spec explicitly promises† that no keyword will ever have a trailing underscore. So you are guaranteed that any naming you create with a trailing underscore will never collide with a keyword or reserved word.
I name all my columns, constraints, etc. in the database with a trailing underscore. Seems a bit weird at first, but you get used to seeing it. Turns out to have a nice side-effect: In all the programming as well as notes and emails, when I see the trailing underscore I know the context is the database as opposed to a programming variable or a business term.
Another benefit is peace-of-mind. Such a relief to eliminate an entire class of possible bugs and weird problems due to keyword collision. If you are thinking, "No big deal - what's a few SQL keywords to memorize and avoid", think again. There are a zillion keywords and reserved words, a zillion being over a thousand.
The answer by Shiva is correct as well: Adding quotes around the name, "GROUP", does solve the problem. The downside is that remembering to add those quotes will be tiresome and troublesome.
Further tip: For maximum compatibility across various SQL databases, do your naming in all lowercase. The SQL spec says that all names should be stored in uppercase while tolerating lowercase. But unfortunately some (most?) databases fail to follow the spec in that regard. After hours of study of various databases, I concluded that all-lowercase gives you maximum portability.
So I actually suggest you name your column: group_
Multiple word names look like this: given_name_ and date_of_first_contact_
† I cannot quote the SQL spec because it is copyright protected, unfortunately. In the SQL:2011 spec, read section 5.4 Names and identifiers under the heading Syntax Rules item 3, NOTE 111. In SQL-92 see section 5.2, item 11. Just searching for the word underscore will work.
I've been facing the same problem recently, my table has columns "key" and "level", both of which are keywords. So instead of renaming the actual tables or bastardising the DB/configuration in any other way, just for the coughing test, the fix was to put the following in the driver configuration in application.properties:
jdbc.url=jdbc:h2:mem:db;NON_KEYWORDS=KEY,LEVEL
And beyond that, I did not have to change a thing in Hibernate/entity settings and JPA was happy and never complained again.
see details here:
https://www.h2database.com/html/commands.html#set_non_keywords
You have to surround the reserved word column name in quotes, like so
"GROUP"
Source (direct link): h2database.com
Keywords / Reserved Words
There is a list of keywords that can't be used as identifiers (table
names, column names and so on), unless they are quoted (surrounded
with double quotes). The list is currently:
CROSS, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, DISTINCT,
EXCEPT, EXISTS, FALSE, FOR, FROM, FULL, GROUP, HAVING, INNER,
INTERSECT, IS, JOIN, LIKE, LIMIT, MINUS, NATURAL, NOT, NULL, ON,
ORDER, PRIMARY, ROWNUM, SELECT, SYSDATE, SYSTIME, SYSTIMESTAMP, TODAY,
TRUE, UNION, UNIQUE, WHERE
Certain words of this list are keywords because they are functions
that can be used without '()' for compatibility, for example
CURRENT_TIMESTAMP.
I've been having this problem with SQL generated by JPA... Turned out I was using a variable name called limit.
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "CREATE TABLE EXPENSE_LIMIT (ID BIGINT NOT NULL, LIMIT[*] DECIMAL(19,2), ACCOUNT_ID BIGINT, EXPENSE_CATEGORY_ID BIGINT, PERIOD_ID BIGINT, PRIMARY KEY (ID)) "; expected "identifier"; SQL statement:
Where my model class had a field called limit.
The fix is to specify column name as
#Column(name = "`limit`")

invalid identifier for creating table

create table ROOM
(NO_ROOM INT PRIMARY KEY, TYPE VARCHAR2(8) NOT NULL, SIZE VARCHAR2(8) NOT NULL)
;
I get ORA-00904, i think problem is from NO_ROOM. I try to use NUMBER, it's same.
PS. I make table for room that has no.room type and size.
SIZE is a reserved keyword. That means we cannot use it as an identifier (unless we put it in double quotes, but double-quoted identifiers are Teh Suck! so don't do that). Change the column name to ROOMSIZE and your statement will run.
Note that TYPE is also a keyword but not reserved. So we are allowed to use it as a column identifier. Types weren't introduced until 8; making TYPE a reserved keyword would have broken code in Oracle applications all over the world, not least in its own data dictionary.
The documentation has a complete list of the reserved words. Find it here.
Why would using "SIZE" be such a bad idea? After all, as #JavaBeginner says, the SQL standard does permit it.
Once we choose to use double-quotes to get around Oracle's naming rules we are condemned to use them whenever we reference the column. Hence this would not be a valid query:
select no_room, size
from room
where size > 10
We would have to write instead:
select no_room, "SIZE"
from room
where "SIZE" > 10
And it always have to be "SIZE": "size" is a different identifier. so is "Size".
Best practice is the informed interpretation of what the standards permit. SQL allows us to do things which we shouldn't do if we want to build a robust and maintainable database. Not using double-quoted identifiers falls into that category.
Size is a keyword and it cannot be used as column name unless you use it with double quotes. My suggestion is to use some other name for column as room_size. If you still want to use SIZE as column name for some reason, you will need to use double quotes while creating the table and also take care of the same while doing any other queries using this column.
Here is the working fiddle with size used as column name http://sqlfiddle.com/#!4/7e746
I do want to add(same as above) that using reserved word for column name(using double quotes) is a bad idea.
You can't use any of these reserved words as identifiers:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/ap_keywd.htm
Size is in the list. If you choose another name for the column you should be okay.
SIZE is a reserved word by Oracle! So, it's not allowed to use them as a name of variables or objects. You can find here http://docs.oracle.com/cd/B28359_01/appdev.111/b31231/appb.htm list of reserved words for Oracle 11g.
Here is the second moment, you can use it inside double quote like "SIZE" or "Size", but that will be case sensitive and not recommended.

Table or column name cannot start with numeric?

I tried to create table named 15909434_user with syntax like below:
CREATE TABLE 15909434_user ( ... )
It would produced error of course. Then, after I tried to have a bit research with google, I found a good article here that describe:
When you create an object in PostgreSQL, you give that object a name. Every table has a name, every column has a name, and so on. PostgreSQL uses a single data type to define all object names: the name type.
A value of type name is a string of 63 or fewer characters. A name must start with a letter or an underscore; the rest of the string can contain letters, digits, and underscores.
...
If you find that you need to create an object that does not meet these rules, you can enclose the name in double quotes. Wrapping a name in quotes creates a quoted identifier. For example, you could create a table whose name is "3.14159"—the double quotes are required, but are not actually a part of the name (that is, they are not stored and do not count against the 63-character limit). ...
Okay, now I know how to solve this by use this syntax (putting double quote on table name):
CREATE TABLE "15909434_user" ( ... )
You can create table or column name such as "15909434_user" and also user_15909434, but cannot create table or column name begin with numeric without use of double quotes.
So then, I am curious about the reason behind that (except it is a convention). Why this convention applied? Is it to avoid something like syntax limitation or other reason?
Thanks in advance for your attention!
It comes from the original sql standards, which through several layers of indirection eventually get to an identifier start block, which is one of several things, but primarily it is "a simple latin letter". There are other things too that can be used, but if you want to see all the details, go to http://en.wikipedia.org/wiki/SQL-92 and follow the links to the actual standard ( page 85 )
Having non numeric identifier introducers makes writing a parser to decode sql for execution easier and quicker, but a quoted form is fine too.
Edit: Why is it easier for the parser?
The problem for a parser is more in the SELECT-list clause than the FROM clause. The select-list is the list of expressions that are selected from the tables, and this is very flexible, allowing simple column names and numeric expressions. Consider the following:
SELECT 2e2 + 3.4 FROM ...
If table names, and column names could start with numerics, is 2e2 a column name or a valid number (e format is typically permitted in numeric literals) and is 3.4 the table "3" and column "4" or is it the numeric value 3.4 ?
Having the rule that identifiers start with simple latin letters (and some other specific things) means that a parser that sees 2e2 can quickly discern this will be a numeric expression, same deal with 3.4
While it would be possible to devise a scheme to allow numeric leading characters, this might lead to even more obscure rules (opinion), so this rule is a nice solution. If you allowed digits first, then it would always need quoting, which is arguably not as 'clean'.
Disclaimer, I've simplified the above slightly, ignoring corelation names to keep it short. I'm not totally familiar with postgres, but have double checked the above answer against Oracle RDB documentation and sql spec
I'd imagine it's to do with the grammar.
SELECT 24*DAY_NUMBER as X from MY_TABLE
is fine, but ambiguous if 24 was allowed as a column name.
Adding quotes means you're explicitly referring to an identifier not a constant. So in order to use it, you'd always have to escape it anyway.