When naming columns in a SQL Server table, are there any names I should avoid using? - sql-server

I remember when I was working with PHP several years back I could blow up my application by naming a MySQL column 'desc' or any other term that was used as an operator.
So, in general are there names I should avoid giving my table columns?

As long as you surround every column name with '[' and ']', it really doesn't matter what you use. Even a space works (try it: [ ]).
Edit: If you can't use '[' and ']' in every case, check the documentation for characters that are not allowable as well as keywords that are intrinsic to the system; those would be out of bounds. Off the top of my head, the characters allowed (for SqlServer) for an identifier are: a-z, A-Z, 0-9, _, $, #.

in general don't start with a number, don't use spaces, don't use reserved words and don't use non alphanumeric characters
however if you really want to you can still do it but you need to surround it with brackets
this will fail
create table 1abc (id int)
this will not fail
create table [1abc] (id int)
but now you need to use [] all the time, I would avoid names as the ones I mentioned above

Check the list of reserved keywords as indicated in other answers.
Also avoid using the "quoting" using quotes or square brackets for the sake of having a space or other special character in the object name. The reason is that when quoted the object name becomes case sensitive in some database engines (not sure about MSSQL though)
Some teams use the prefix for database objects (tables, views, columns) like T_PERSON, V_PERSON, C_NAME etc. I personally do not like this convention, but it does help avoiding keyword issues.

You should avoid any reserved SQL keywords (ex. SELECT) and from a best practices should avoid spaces.

Yes, and no.
Yes, because it's annoying and confusing to have names that match keywords, and that you have to escape in funny ways (when you're not consistently escaping)
and No, because it's possible to have any sequence of characters as an identifier, if you escape it properly :)
Use [square brackets] or "double quotes" to escape multi-word identifiers or keywords, or even names that have backslashes or any other slightly odd character, if you must.

Strictly speaking, there's nothing you can't name your columns. However, it will make your life easier if you avoid names with spaces, SQL reserved words, and reserved words in the language you're programming in.

You can use pretty much anything as long as you surround it with square brackets:
SELECT [value], [select], [insert] FROM SomeTable
I however like to avoid doing this, partly because typing square brackets everywhere is anoying and partyly because I dont generally find that column names like 'value' particularly descriptive! :-)
Just stay away from SQL keywords and anything which contains something other than letters and you shouldn't need to use those pesky square brackets.

You can surround a word in square brackets [] and basically use anything you'd like.
I prefer not to use the brackets, and in order to do so you just have to avoid reserved words.
MS SQL Server 2008 has these reserved words

Beware of using square brackets on updates, I had a problem using the following query:
UPDATE logs SET locked=1 WHERE [id] IN (SELECT [id] FROM ids)
This caused all records to be updated, however, this appears to work fine:
UPDATE logs SET locked=1 WHERE id IN (SELECT [id] FROM ids)
Note that this problem appears specific to updates, as the following returns only the rows expected (not all rows):
SELECT * FROM logs WHERE [id] IN (SELECT [id] FROM ids)
This was using MSDE 2000 SP3 and connecting to the database using MS SQL (2000) Query Analyzer V 8.00.194
Very odd, possibly related to this Knowledgebase bug http://support.microsoft.com/kb/140215
In the end I just removed all the unnecessary square brackets.

Related

Escape special characters for Oracle and SQL Server in the same query

I have following query:
SELECT *
FROM PRODUCTS
WHERE REDUCTION LIKE '50%'
I'm required to use the LIKE clause. This query needs to run on both Oracle and SQL Server.
Now there is an issue because I want to match all products with a reduction of 50%. But the data might contain a reduction of 50.50%. Because '%' is a special character it matches both of them.
I want to escape all special characters, like the % in my query so that I only get the products with 50% reduction.
Is there an uniform solution to escape special characters on a dynamical way for both Oracle and SQL server?
Using a backslash is not a solution, because we don't know in practice what the input will be.
The ESCAPE clause works in Oracle and SQL Server.
As for your input, you need to replace the all occurrences of % with \% (preferably before passing the value to RDBMs). You can do this inside a query as well since, fortunately, Oracle REPLACE and SQL Server REPLACE functions have similar signature:
CREATE TABLE tests(test VARCHAR(100));
INSERT INTO tests VALUES('%WINDIR%\SYSTEM32');
SELECT *
FROM tests
WHERE test LIKE REPLACE(REPLACE('%WINDIR%\SYSTEM32', '\', '\\'), '%', '\%') ESCAPE '\'
The ESCAPE clause identifies the backslash (\) as the escape character
SELECT *
FROM PRODUCTS
WHERE REDUCTION LIKE '50\%'
You'll need something like the first answer above, but you don't need to use a \ as the escape. You can choose whatever you want using the ESCAPE clause.
But if:
users are allowed to enter wildcards;
and you need to use LIKE;
and you don't want them treated like wildcards;
then you have to escape them somehow.
Perhaps you can reserve some char you know the user will not need and make that the escape char.
As far as I can tell in Oracle you only need to escape the percent (%) and the underbar (_).
In SQL Server you also have to consider brackets.
A good thing is that overescaping does not look like it will cause problems, so even though you don't need to espace brackets in Oracle, doing so is ok.

SQL would using between statement improve this?

I want to find out using a select statement what columns in a table share similar information.
Example: Classes table with ClassID, ClassName, ClassCode, ClassDescription columns.
This was part of my SQL class that I already turned in. The question asked "What classes are part of the English department?"
I used this Select statement:
SELECT *
FROM Classes
WHERE ClassName LIKE "English%" OR ClassCode LIKE "ENG%"
Granted we have only input one actual English course in this database, the end result was it executed fine and displayed everything for just the English class. Which I thought was a success since we did populate other non English courses in the database.
Anyways, I was told I should have used a BETWEEN statement.
I am just sitting here thinking they would both do what I needed them to do right?
I'm using SQL Server 2014
No, BETWEEN would probably be a bad idea here. BETWEEN doesn't allow wildcards and doesn't do any pattern matching in any RDBMS I've used. So you'd have to say BETWEEN 'ENG' AND 'English'. Except that doesn't return things like 'English I' (which would be after 'English' in a sorted list).
It would also potentially include something like 'Engineering' or 'Engaging Artistry', but that's a weakness of your existing query, too, since LIKE 'ENG%' matches those.
If you happen to be using a case-sensitive collation you add a whole new dimension of complexity. Your BETWEEN statement gets even more confusing. Just know that capital letters generally come before lower case letters, so 'ENGRAVING I' would be included but 'Engraving I' would not. Additionally, 'eng' would not be included. Note that case-insensitive collation is the default.
Also whats the difference when searching for null values in one table
and one column
column_name =''
or
column_name IS NULL
You're not understanding the difference between an empty string and null.
An empty string is explicit. It says "This field has a known value and it is a string of zero length."
A null string is imprecise. It means "unknown". It could mean "This value wasn't asked for," or "This value was not available," or "This value has not yet been determined," or "This values does not make sense for this record."
"What is this person's middle name?"
"He doesn't have one. See, his birth certificate has no middle name listed." --> Empty string
"I don't know. He never told me and I don't have any birth or identity record." --> NULL
Note that Oracle, due to backwards compatibility, treats empty strings as NULLs. This is explicitly against ANSI SQL, but since Oracle is that old and that's how it's always worked that's how it will continue to work.
Another way to look at it is the example I tend to use with numbers. The difference between 0 and NULL is the difference between having a bank account with $0 balance and not having a bank account at all.
Nothing can be said unless we see table and its data.Though don't use between.
Secondly first find which of the column is not null by design.Say for example ClassName cannot be null then there is no use using ClassCode LIKE "ENG%",just ClassName LIKE "English%" is enough,similarly vice versa is also true.
Thirdly you should use same parameter in both column.for example
ClassName LIKE "English%" OR ClassCode LIKE "English%"
see the difference.
Select * FROM Classes
Where ClassName LIKE "%English%"

Oracle SELECT - Double quotes or no double quotes? [duplicate]

This question already has answers here:
Oracle SQL Syntax: Quoted identifier
(4 answers)
ORA-00904: invalid identifier
(13 answers)
Closed 9 years ago.
All,
When writing SELECT queries for Oracle 11i databases, why do some tables in Oracle enforce applying quotation marks to the fields being selected, and others not.
An example I've recently come across:
In Aqua Data Studio in a Query Analyzer window I have attempted to select the same field from two different tables:
select _id from table1
select _id from table2
table1 and table2 differ greatly, but Only table1 executes this select statement without an error. When I try to execute this statement for table2 I get the following:
ORA-00904: "_ID": invalid identifier
Script line 1, statement line 1, column 7
However, when I execute the second statement like this it works perfectly:
select "_id" from table2
Does anyone know what is going on here, why is this the case, and what could the key differences be between the tables be that is causing this?
Thanks
The answers and links about casing are correct, but your situation goes a little beyond a simple case issue, both because your column name started with an underscore and because your client is apaprently usually hiding the quoting from you.
If you tried to create a table with a column called _id, without quoting it, then you'd get an 'ORA-00911: invalid character' error, the cause text of which says 'identifiers may not start with any ASCII character other than letters and numbers'; which is actually wrong as well since it can't start with a number either (for example, 0_id gives 'ORA-00904: : invalid identifier'). This is backed up by the database object naming rules:
Nonquoted identifiers must begin with an alphabetic character from your database character set. Quoted identifiers can begin with any
character.
So it looks like Aqua Data Studio is following a convention of enclosing the upper-case version of the object name you supply in double-quotes, a practice mentioned in one of the linked posts.
From what you've shown, select _id from ... gets passed to Oracle as select "_ID" from ..., which is fine if the column name was created as "_ID". It appears that is the case for table1, but table2 was created as "_id" - so that case mismatch generates the legitimate ORA-00904 you're seeing.
Your client is not modifying a column name that is already enclosed in double-quotes, so select "_id" from ... is passed through to Oracle as-is, and works OK for table2 (but, conversely, would fail for table1).
Oracle requires the name to be enclosed in double quotes if it doesn't follow the rules for unquoted identifiers, and if it was created as quoted - unless the original quoted value was valid anyway, i.e. follows the unquoted rules and was entered in uppercase. Since your column name starts with an underscore, as far as Oracle is concerned all references to it have to be enclosed in double-quotes regardless of the case. Your client is just doing that in the background if you haven't quoted it yourself.
Following the advice others have given to avoid quoted identifiers and to always use names that are valid unquoted would avoid issues like this.
The problem comes from the creation of the object.
If you create an object with lower case AND quotation marks, it will enforce case sensitivity.
So you'll need to use quotation marks and right casing to use it.
If you create without quotes (or all in upper case), you won't face any "case sensitivity" problems, and will be able to select object with lower or upper case (without quotation marks)

SQL Server not accepting alias name

Constructing a SQL Server query for the first time today, and was surprised to see that this alias didn't work:
SELECT
INVOICE_INVOICE_NUMBER AS invno,
INVOICE_INVOICE_SEQ AS lineno
FROM
INVOICED
But this did:
SELECT
INVOICE_INVOICE_NUMBER AS invoice,
INVOICE_INVOICE_SEQ AS line
FROM
INVOICED
Changing the alias name is no big deal - but it would be good to know why this particular alias didn't work and how I can prevent or be aware of any future keywords to avoid.
LineNo is a reserved word. You can encase it in brackets to use it.
SELECT INVOICE_INVOICE_SEQ AS [lineno]
Reserved words
The answer is in your question itself. Keywords change colour and you should be able to easily make that out, unless you are typing your SQL query in notepad. Ideally it is not a good practice to use keywords for aliases, but if you have to, wrap them in square brackets - [ ].
Typically, reserved words turn blue, functions turn pink and system objects turn green. Of course you do have the ability to change the font in SSMS (Options > Environment > Fonts and Colors)
Raj

Why is a space a valid column name in SqlServer?

See for yourself:
create table #temp ([ ] varchar(1))
insert into #temp values ('1')
select [ ] from #temp
What in the world is the rationale for allowing this?
I think the rationale is more along the lines of:
Is it worth preventing this
functionality?
I don't know how SQL is coded internally but I would suspect it would take more effort to prevent this then to allow it.
I use it all the time as a placeholder/seperator when debugging complex queries. I might have something like this:
SELECT a.*, ' ' as [ ], b.*
FROM a
LEFT JOIN b on ...
This way I get a blank section in between the two tables so I can easily see in the results where one stops and the other starts.
Later on when I get the results and performance I need I'll change the select clause to only use the columns I care about.
That said, I suppose there's no reason I couldn't use something else for the column name.
Space is an acceptable character, as some people like to have spaces in their column names. And if it can be a part of a column name then why not a column name by itself?
Why do they ever do it will remain a mystery to me, as it makes programming so much more difficult (constantly enclosing everything in "" or []). I have actually seen a column name with a question mark, which is definitely something I would avoid using in any identifier, but it's possible, still.
Any valid characters can be used in between [] to define the column & table names.
Given that something like [A Column] is valid (with space), there is no reason to prevent a single space as a column name.
However, trailing spaces are removed so. [ ] and [ ] (1 & 2 spaces)
will be both treated as
[ ] (1 space).
I guess a space is just like any other character. You can even create a table named [ ]. (I tried it, and it worked.) I think there are simply no restrictions on this.
I kinda appreciate the assumption that I'm responsible enough not to hurt myself with potentially dangerous features. I haven't found a good reason for spaces in object names myself, but it seems to be popular in some cases. This is an extreme example of running with scissors.

Resources