Why is this very simple SQL query failing in MS Access? - sql

I have a query that by all rights should not possibly fail, and I can't for the life of me figure out why
INSERT INTO Grocery_Store_Prices(Store,Item,Brand,Price,Unit,Quantity,Note)
VALUES("Kroger","Cheesy Poof","Cartman",0.51,"fart",15,"what is going on");
When I try to run the query I get "Syntax error in INSERT INTO statement" with the Note field highlighted. If I omit the Note field and its value, the query works fine. Is there something really obvious I'm missing, or is there an Jet SQL quirk buried here???
The table it's acting on is:
Grocery_Store_Prices
ID -- autonumber primary key
Store -- Text
Date -- Date/Time
Item -- Text
Brand -- Text
Price -- Currency
Unit -- Text
Quantity -- Number (double)
Note -- Text.

"Note" is a reserved word in Microsoft Access. You need to surround it with square brackets:
INSERT INTO Grocery_Store_Prices(Store,Item,Brand,Price,Unit,Quantity,[Note])
VALUES("Kroger","Cheesy Poof","Cartman",0.51,"fart",15,"what the ____");
Helpful list of reserved words here: http://support.microsoft.com/kb/286335
Some consider it best practice to always encase field names in square brackets, just so you don't have to worry about it.
Good luck!

Note is a reserved word, so try renaming that column.

Related

Why does Microsoft SSMS syntax highlight the word "configuration"?

When using Microsoft SQL Server Management Studio 14.0.17254.0 and it's query editor, I noticed that the word configuration is always syntax highlighted as a blue keyword. Even though it doesn't appear to be in the list of Reserved Keywords. Is this a keyword in some other SQL standard or has this been a keyword before? Is there any reason this should be highlighted with the same color as SELECT or WHERE?
I found similar question asking about other keywords, and they all seemed to have logical reasons, but couldn't find anything for this word.
Primary reason for this question is that I want to know if using this as a column name in queries without the the brace encapsulation [configuration] is completely safe.
There are both Reserved Keywords, and Keywords in SQL Server. CONFIGURATION is a keyword, but it isn't reserved. Just like int (for the datatype int), and other words, are a keyword , but you could still use it in a statement unquoted:
CREATE TABLE sample (int int,
date date,
char varchar(10),
last decimal(12,2),
first numeric(12,2),
system char(2));
Every single word there is a keyword of some kind (including sample), but only CREATE and TABLE are reserved. char is even a datatype and a function and isn't reserved, so you could have a nonsensical statement like CONVERT(char,CHAR(Char)), and every reference to "char" has a different meaning.
CONFIGURATION isn't a future keyword either, so at this time, you would seem fine to use it.

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.

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.