If some one does right click on a given Table in a Database using SQL Server management Studio from Microsoft and create script table to query window, it displays the create table code in the window. I notice something like the following
CREATE TABLE [dbo].[Login](
[UserId] [int] NOT NULL,
[LoginName] nvarchar COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
etc
)
Is this how it appears in other DBMS too ?
Is this something specific to DBMS used ?
Is it just a fancy view only ?
Why are "[ ]" used around column names and table names. Simple TSQL definition would look something like
CREATE TABLE table_name (
Column#1 Datatype NOT NULL,
Column#2 Datatype NOT NULL UNIQUE,
-- etc...
)
Please dont mind my silly questions.
Thanks in advance,
Balaji S
Those are identifier quotes. They mark the contents as a database identifier (column name, table name, etc) and allow spaces, special characters, and reserved words to be used as identifiers. Usually none of those appear in identifiers so the ID quotes are, strictly speaking, unnecessary. When the text cannot be parsed because of special characters or reserved words, the ID quotes are required.
It's easier for automated tools to simply always use the ID quotes than figure out when you could get away without them.
Different database products use different characters for ID quotes. You often see the back-tick (`) used for this.
Just to add to Larry Lustig's excellent answer, SQL Server's 'create script' function spits out SQL code whose first priority is to be parser-friendly and that's why it always uses its preferred delimited identifier characters being square brackets, rather than say the double quotes used by the SQL-92 standard (SQL Server code can support the Standard delimited identifier by the use of SET QUOTED_IDENTIFIER ON but I don't think this can be specified as an option for output). Being easy on the human eye (use of whitespace, line breaks, etc) is merely a secondary consideration.
Related
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`")
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.
Java DB / Derby - white space in table (column) name - how to escape? In MySQL database it is escaped simply by `` (grave accent), but if I trying to execute query (Java DB) like:
CREATE TABLE `etc etc` (ID INT PRIMARY KEY, Title VARCHAR(12))
I get the error:
java.sql.SQLSyntaxErrorException: Lexical error at line 1, column 14.
Encountered: "`" (96), after : "".
Is there any solution?
EDITED:
Thanks for comprehensive answers indeed. I found interesting thing (Java DB):
it was OK to create table like this:
CREATE TABLE "etc etc" (ID INT PRIMARY KEY, Title VARCHAR(12))
and later to get the results:
SELECT * FROM "etc etc"
But if I create the table like this (without white space and quotes):
CREATE TABLE etc_etc (ID INT PRIMARY KEY, Title VARCHAR(12))
and later get the results like this (with double quotes, just for example, they don't really needed):
SELECT * FROM "etc_etc"
I get the error:
java.sql.SQLSyntaxErrorException: Table/View 'etc_etc' does not exist.
So my conclusion is that if quotes were used while creating the table (it is not important if the name contains white space or not), later, while getting the results, quotes also should be used. And vice versa (int this case of course without white space).
I agree it is better not to use white space, instead _ character. But I liked on MySQL those ` grave accent characters...
The SQL standard requires double quotes to quote identifiers that are either reserved words or use characters otherwise not permitted in an identifier. Note that MySQL simply ignores the standard by using the dreaded backtick ` - but it could (and in my opinion should) be configured to also allow the standard double quotes (like all other DBMS do).
So your statement should look like this:
CREATE TABLE "etc etc" (ID INT PRIMARY KEY, Title VARCHAR(12));
Note that the use of "quoted identifiers" (or "delimited identifiers") also makes the name case sensitive. "etc etc" is a different table name than "Etc Etc". So after creating the table like above, you always have to write the name in lowercase.
The best thing is to completely avoid quoted identifiers. So in your case you should probably settle for etc_etc as the name using an underscore to visually separate the two words.
This question already has answers here:
What is the use of the square brackets [] in sql statements?
(10 answers)
Closed 7 years ago.
I have a copy of an existing database with existing records. when i was playing around with the table designer and noticed some of the column names have [] around them. they all seem to be arbitrary typed (float, datetime, netext, nvarchar etc) and there is nothing in column properties that gets rid of the []. I tried to rename delete the [] but it reappaears as soon as I exit edit.
according to this post, it is a keyword column for xml columns? but none of those columns are xml columns. Would someone kindly explain the purpose of this to a ms-sql newbie? thanks
The square brackets [] are used to delimit identifiers. This is necessary if the column name is a reserved keyword or contains special characters such as a space or hyphen.
Some users also like to use square brackets even when they are not necessary.
From MSDN:
Delimited identifiers
Are enclosed in double quotation marks (") or brackets ([ ]). Identifiers that comply with the rules for the format of identifiers may or may not be delimited.
SELECT *
FROM [TableX] --Delimiter is optional.
WHERE [KeyCol] = 124 --Delimiter is optional.
Identifiers that do not comply with all of the rules for identifiers must be delimited in a Transact-SQL statement.
SELECT *
FROM [My Table] --Identifier contains a space and uses a reserved keyword.
WHERE [order] = 10 --Identifier is a reserved keyword.
Square brackets may be placed around objects (e.g. views, databases, columns etc)
Their primary purpose is, as Mark mentioned, to encapsulate the objects so that special characters such as a space or period do not interfere with your syntax.
Many applications by default use the bracketed notation, to further reduce risk of syntax errors or anything of that sort.
It's typically good practice to not include any spaces
Database_Name < GOOD PRACTICE
Database Name < GENERALLY TRY TO AVOID
In any case, if the latter is used, you may use square brackets i.e.
select * from [Database Name]
the brackets are special characters in sql server that are used to explicitly delimit information.
they can be used in xml as per the article, they can also be used to specify meta names (column, table, etc.) that have spaces or other key words.
declare my column nvarchar(50)
would be invalid syntax, but you could do
declare [my column] nvarchar(50)
just think of them as explicit delimiters.
I'm looking to perform case-insensitive search in a Firebird database, without modifying actual queries. In other words, I'd like all my existing "SELECT/WHERE/LIKE" statements to retrieve BOB, Bob, and bob. Does Firebird configuration allow to modify this behavior?
Try using something like:
Imagine you have a table of persons like this one:
CREATE TABLE PERSONS (
PERS_ID INTEGER NOT NULL PRIMARY KEY,
LAST_NAME VARCHAR(50),
FIRST_NAME VARCHAR(50)
);
Now there is an application, which allows the user to search for persons by last name and/or first name. So the user inputs the last name of the person he is searching for.
We want this search to be case insensitive, i.e. no matter if the user enters "Presley", "presley", "PRESLEY", or even "PrESley", we always want to find the King.
Ah yes, and we want that search to be fast, please. So there must be an index speeding it up.
A simple way to do case insensitive comparisons is to uppercase both strings and then compare the uppercased versions of both strings.
Uppercasing has limitations, because some letters cannot be uppercased. Note also that there are languages/scripts where there is no such thing as case. So the technique described in this article will work best for European languages.
In order to get really perfect results one would need a case insensitive (CI) and/or accent insensitive (AI) collation. However, at the time of this writing (July 2006) there are only two Czech AI/CI collations for Firebird 2.0. The situation will hopefully improve over time.
(You should know the concepts of Character Sets and Collations in order to understand what comes next. I use the DE_DE collation in my examples, this is the collation for German/Germany in the ISO8859_1 character set.)
In order to get correct results from the UPPER() function that is built into Firebird, you must specify a collation. This can be in the DDL definition of the table:
CREATE TABLE PERSONS (
PERS_ID INTEGER NOT NULL PRIMARY KEY,
LAST_NAME VARCHAR(50) COLLATE DE_DE,
FIRST_NAME VARCHAR(50) COLLATE DE_DE
);
or it can be done when calling the UPPER() function:
SELECT UPPER (LAST_NAME COLLATE DE_DE) FROM PERSONS;
http://www.destructor.de/firebird/caseinsensitivesearch.htm
or you can edit your queries and add the lower() function
LOWER()
Available in: DSQL, ESQL, PSQL
Added in: 2.0
Description: Returns the lower-case equivalent of the input string. This function also correctly lowercases non-ASCII characters, even if the default (binary) collation is used. The character set must be appropriate though: with ASCII or NONE for instance, only ASCII characters are lowercased; with OCTETS, the entire string is returned unchanged.
Result type: VAR(CHAR)
Syntax:
LOWER (str)
Important
If the external function LOWER is declared in your database, it will obfuscate the internal function. To make the internal function available, DROP or ALTER the external function (UDF).
Example:
select field from table
where lower(Name) = 'bob'
http://www.firebirdsql.org/refdocs/langrefupd21-intfunc-lower.html
Necromancing.
Instead of a lowercase-field, you can specify the collation:
SELECT field FROM table
WHERE Name = 'bob' COLLATE UNICODE_CI
See
https://firebirdsql.org/refdocs/langrefupd21-collations.html
Maybe you can also specify it as the default character-set for the database, see
http://www.destructor.de/firebird/charsets.htm
Eventually I went with creating shadow columns containing lower-cased versions of required fields.