SQL Check Statement for Zip Code using escape character - sql

I have tried looking in other areas, but I can't seem to figure out what is wrong with what I am doing. I am trying to create a check constraint on a column that is supposed to contain a 9 digit zip code formatted as "00000-0000". This is for an assignment, so the only thing I am allowed to do is create the check constraint.
I have already used the check statement successfully for other columns, but for some reason the statement that I found here on Stack Overflow does not work. The only allowed characters are numbers and the hyphen character ('-').
alter table Student
add constraint student_zip_ck
check (Zip not like '%[0-9\-]%' escape '\');
Since this check constraint was modelled after another (positively-rated) question on Stack Overflow, I don't know what could be wrong. This is the error I receive.
Error starting at line 751 in command:
alter table Student
add constraint student_zip_ck
check (Zip not like '%[0-9\-]%' escape '\')
Error report:
SQL Error: ORA-00604: error occurred at recursive SQL level 1
ORA-01424: missing or illegal character following the escape character
00604. 00000 - "error occurred at recursive SQL level %s"
*Cause: An error occurred while processing a recursive SQL statement
(a statement applying to internal dictionary tables).
*Action: If the situation described in the next error on the stack
can be corrected, do so; otherwise contact Oracle Support.
Does anyone have suggestions, questions, or comments for me?

You're missing anything related to regular expressions, which is probably why it isn't working. Your syntax implies you meant to use them and I would agree with that in this situation. Regular expressions have been available since Oracle 10g so you have to ensure that you're using this version or higher.
The syntax would become:
alter table Student
add constraint student_zip_ck
check (regexp_like(Zip,'^[[:digit:]]{5}-[[:digit:]]{4}$'));
This means:
^ - pin to the beginning of the string
[[:digit:]] - accept only numeric values. This is the POSIX compliant variation and is equivalent to \d.
{5} - 5 times exactly
- - match a hyphen
$ - pin to the end of a string
To make the hyphen and the second for digits optional you need to create a group using (). This makes everything within the parenthesis a single unit, whether it's a string or another regular expression, which you can then apply other operators to. A ? means match 0 or 1 times, and needs to be applied to the group. Putting it all together you get:
regexp_like(Zip,'^[[:digit:]]{5}(-[[:digit:]]{4})?$')
Further Reading
Regular expression documentation 11.2
Reading this (for the first time) there's a fairly similar problem, example 3-1, which uses the Perl type regular expression syntax \d instead of the POSIX and may be of interest.

LIKE operator uses wildcards (% and _) - http://docs.oracle.com/cd/F49540_01/DOC/server.815/a67779/operator.htm#997970
for regular expressions, try REGEXP_LIKE() function - http://www.regular-expressions.info/oracle.html

Related

referencing columns - pgAdmin 4

When using the Query tool in pgAdmin4 for Postgres, I have to use double quotes "" if I want to reference columns in a query.
Can this be altered so that double quotes are not needed? I have my database setup in Manjaro yet I have the same setup on another system in Ubuntu and I am 99% sure that on that install, I do not need to use double quotes in the query tool.
Does anyone know if this is a setting that could be amended as it is really annoying having to put all column references into double quotes all the time
This simple select query fails:
SELECT saleDate,qty,saleAmount FROM sales
and I get the following error:
HINT: Perhaps you meant to reference the column "sales.saleDate". SQL state: 42703 Character: 8
Yet this works fine:
SELECT "saleDate", "qty", "saleAmount" FROM sales
Would just be nice not to have to reference every single column with ""'s
You only have to use double quotes for case sensitive identifiers or identifiers including special characters or that are reserved words.
Simply avoid using such identifiers when creating objects, then you don't need to double quote them later on.
The identifiers in the database don't need to be "pretty" after all. The presentation layer should handle that.
4.1.1. Identifiers and Key Words:
Quoting an identifier also makes it case-sensitive, whereas unquoted names are always folded to lower 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. (The folding of unquoted names to lower case in PostgreSQL is incompatible with the SQL standard, which says that unquoted names should be folded to upper case. Thus, foo should be equivalent to "FOO" not "foo" according to the standard. If you want to write portable applications you are advised to always quote a particular name or never quote it.)

Is it possible to have a % symbol in my column name?

I'm trying to add a new column to an existing table, but when I try to create this column name I'm getting an invalid character error.
SQL Error: ORA-00911: invalid character
00911. 00000 - "invalid character"
*Cause: identifiers may not start with any ASCII character other than
letters and numbers. $#_ are also allowed after the first
character. Identifiers enclosed by doublequotes may contain
any character other than a doublequote. Alternative quotes
(q'#...#') cannot use spaces, tabs, or carriage returns as
delimiters. For all other contexts, consult the SQL Language
Reference Manual.
This is my code:
Alter Table Calculations
Add WEIGHTED_% Number;
What am I doing wrong?
I really don't recommend using the % symbol in you name I would recommend typing Percent instead. But as the error says you must en-capsule you column name in double quotes.
Alter Table Calculations Add "WEIGHTED_%" Number;
Not sure then it would still work because % is a reserved character for Doing like query and including them in exposed query is considered a vulnerability because it allows SQL injection.
Yes. Possible. Use double code for column name. Check the attached screen shot.
But it's not good to use % in the column name. Not recommended.

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`")

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.

What's the significance of # in SQL?

I have the following code to create an object type in Oracle (PL??)
CREATE OR REPLACE TYPE STAFF_T as OBJECT(Staff_ID# NUMBER, Person PERSON_T); \
I'd like to know what is the significance of the # appended to the Staff_ID variable in the declaration?
No special meaning.
Oracle allows using $, _ and # in identifiers, just like any other alphanumeric characters, but the identifier should begin with an alpha character (a letter).
That's part of the column name Staff_ID#. The pound sign is an allowable part of an identifier (table/column name) in PL/SQL. See here
Whoever wrote the code probably didn't mean anything special by #.
But # apparently means something to Oracle, although I don't know what. From the SQL Language Reference:
Oracle strongly discourages you from
using $ and # in nonquoted
identifiers.
Here are some guesses for what the warning is about:
it's related to a really old bug (the
warning goes back to at least Oracle
7)
Oracle plans to do something with
it in a future verison
that character
isn't available on all keyboards, character sets, or platforms that Oracle supports
The data dictionary uses the number sign a lot, and as far as I can tell it works just fine for user objects. But just to be safe you might want to remove it.