Java DB / Derby - white space in table name - how to escape? - sql

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.

Related

MS SQL fulltext search with ignoring special characters

I have a following (simplified) database structure:
[places]
name NVARCHAR(255)
description TEXT (usually quite a lot of text)
region_id INT FK
[regions]
id INT PK
name NVARCHAR(255)
[regions_translations]
lang_code NVARCHAR(5) FK
label NVARCHAR(255)
region_id INT FK
In real db I have few more fields in [places] table to search in, and [countries] table with similar structure to [regions].
My requirements are:
Search using name, description and region label, using the same behaviour as name LIKE '%text%' OR description LIKE '%text5' OR regions_translations.label LIKE '%text%'
Ignore all special characters like Ą, Ć, Ó, Š, Ö, Ü, etc. so for example, when someone search for
PO ZVAIGZDEM I return a place with name PO ŽVAIGŽDĖM - but of course also return this record, when user uses proper characters with accents.
Quite fast. ;)
I had a few approaches to solve this issue.
Create new column 'searchable_content', normalize text (so replace Ą -> A, Ö -> O and so on) and just do simple SELECT ... FROM places WHERE searchable_content LIKE '%text%' but it was slow
Add fulltext search index to table places and regions_translations - it was faster, but I could not find a way to ignore special characters (characters are from various of languages, so specyfying index language will not work)
Create new column as in first attempt, and addfulltext index only on that column - it was faster then attempt 1 (probably because I do not need to join tables) and I could manually normalize the content, but I feel like it's not a great solution.
Question is - what is the best approach here?
My top priority is to ignore special characters.
EDIT:
ALTER FULLTEXT CATALOG [catalog_name] REBUILD WITH ACCENT_SENSITIVITY = OFF
Probably is a solution to my issue with special characters (need to test it a bit more) - I query too fast, and index did not rebuild, that's why I did not get any records.
You can use the COLLATE clause on a column to specify a sql collation that will treat these special characters as their non-accented counterparts. Think of it as essentially casting one data type as another, except you're casting é as e (for example). You can use the same tool to return case sensitive or case insensitive results.
The documentation talks a little more about it, and you can do a search to find exactly which collation works best for you.
https://learn.microsoft.com/en-us/sql/t-sql/statements/collations?view=sql-server-ver16

HSQL Query constraint for alphabets and numbers

How I have a column Firstname which should be only Alphabets
and phone number which should be only numbers in HSQL
i wrote something like
ALTER TABLE USER
ADD CONSTRAINT CHECK_USER_FIRST_NAME CHECK (FIRST_NAME NOT LIKE '%[^A-Z ]%' )
But it allows Tp1 which i don't want.
Can someone help me with constraint in HSQL
LIKE doesn't support regular expressions. The only wildcards it supports are % for multiple characters and _ for a single character. To match against a regular expression you need regexp_matches()
ALTER TABLE user
ADD CONSTRAINT check_user_first_name
CHECK (regexp_matches(first_name, '[A-Z]+'))
This will allow only uppercase letters, so you probably want to use '[A-Za-z]+' instead. It also requires at least one character in the name. If you want to allow empty strings, change the + to *. This will still allow null values though.
Note that USER is a reserved keyword in SQL. You shouldn't create a table with that name. If you try this e.g. on Oracle or PostgreSQL it will fail. The name requires to be quoted - which is not a good idea. You should find a different name.

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.

SQL Create table script from DBMS contains [ ]

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.