Ok, this is bit of an obscure question, but hopefully someone can help me out with it.
The system I'm working on builds a dynamic SQL string for execution inside a stored procedure, and part of that dynamic SQL defining column aliases, which themselves are actually values retrieved from another table of user generated data.
So, for example, the string might look something like;
SELECT table1.Col1 AS "This is an alias" FROM table1
This works fine. However, the value that is used for the alias can potentially contain a double quote character, which breaks the outer quotes. I thought that I could maybe escape double quotes inside the alias somehow, but I've had no luck figuring out how to do so. Backslash doesn't work, and using two double quotes in a row results in this error;
SQL Error: ORA-03001: unimplemented feature
03001. 00000 - "unimplemented feature"
*Cause: This feature is not implemented.
Has anyone had any experience with this issue before?
Cheers for any insight anyone has.
p.s. the quotes are needed around the aliases because they can contain spaces.
Can you just put another character instead of double quotes and replace that with double quotes in the code?
Something like this:
SELECT table1.Col1 AS "This is |not| an alias" FROM table1
Then just replace | with ".
I know it's a hack, but I can't think of any better solution... And what you are doing there is a hack anyway. The "nice" way would be to select the values and the column names separately and associate them in your code. That would make things much cleaner.
use the Oracle quote operator:
select q'#someone's quote#' from dual;
the '#' can be replaced by any character
When I run this:
select 'test"columnname"' from dual
Oracle returns this (notice the Oracle-generated column name):
'TESTCOLUMNNAME'
--------------------------------
test"columnname
The fact that Oracle's column name doesn't include my double-quote tells me that Oracle probably cannot represent that.
Best bet as far as I can see is to strip double-quotes from your data prior to using column names. Sadly, that will also require that you do the same filtering when you select those columns, but I don't see another way.
a possibly fruitful area of investigation would be to look into the quote method.
my $quotedString = $dbh->quote( $string );
Try this, two single quotes actually look like one double quote in output:
select 1 as "University ''John Smith''" from dual;
Related
One of my columns is called from. I can't change the name because I didn't make it.
Am I allowed to do something like SELECT from FROM TableName or is there a special syntax to avoid the SQL Server being confused?
Wrap the column name in brackets like so, from becomes [from].
select [from] from table;
It is also possible to use the following (useful when querying multiple tables):
select table.[from] from table;
If it had been in PostgreSQL, use double quotes around the name, like:
select "from" from "table";
Note: Internally PostgreSQL automatically converts all unquoted commands and parameters to lower case. That have the effect that commands and identifiers aren't case sensitive. sEleCt * from tAblE; is interpreted as select * from table;. However, parameters inside double quotes are used as is, and therefore ARE case sensitive: select * from "table"; and select * from "Table"; gets the result from two different tables.
These are the two ways to do it:
Use back quote as here:
SELECT `from` FROM TableName
You can mention with table name as:
SELECT TableName.from FROM TableName
While you are doing it - alias it as something else (or better yet, use a view or an SP and deprecate the old direct access method).
SELECT [from] AS TransferFrom -- Or something else more suitable
FROM TableName
Your question seems to be well answered here, but I just want to add one more comment to this subject.
Those designing the database should be well aware of the reserved keywords and avoid using them. If you discover someone using it, inform them about it (in a polite way). The keyword here is reserved word.
More information:
"Reserved keywords should not be used
as object names. Databases upgraded
from earlier versions of SQL Server
may contain identifiers that include
words not reserved in the earlier
version, but that are reserved words
for the current version of SQL Server.
You can refer to the object by using
delimited identifiers until the name
can be changed."
http://msdn.microsoft.com/en-us/library/ms176027.aspx
and
"If your database does contain names
that match reserved keywords, you must
use delimited identifiers when you
refer to those objects. For more
information, see Identifiers (DMX)."
http://msdn.microsoft.com/en-us/library/ms132178.aspx
In Apache Drill, use backquotes:
select `from` from table;
If you ARE using SQL Server, you can just simply wrap the square brackets around the column or table name.
select [select]
from [table]
I have also faced this issue.
And the solution for this is to put [Column_Name] like this in the query.
string query= "Select [Name],[Email] from Person";
So it will work perfectly well.
Hi I work on Teradata systems that is completely ANSI compliant. Use double quotes " " to name such columns.
E.g. type is a SQL reserved keyword, and when used within quotes, type is treated as a user specified name.
See below code example:
CREATE TABLE alpha1
AS
(
SEL
product1
type_of_product AS "type"
FROM beta1
) WITH DATA
PRIMARY INDEX (product1)
--type is a SQL reserved keyword
TYPE
--see? now to retrieve the column you would use:
SEL "type" FROM alpha1
I ran in the same issue when trying to update a column which name was a keyword. The solution above didn't help me. I solved it out by simply specifying the name of the table like this:
UPDATE `survey`
SET survey.values='yes,no'
WHERE (question='Did you agree?')
The following will work perfectly:
SELECT DISTINCT table.from AS a FROM table
Some solid answers—but the most-upvoted one is parochial, only dealing with SQL Server. In summary:
If you have source control, the best solution is to stick to the rules, and avoid using reserved words. This list has been around for ages, and covers most of the peculiarities. One tip is that reserved words are rarely plural—so you're usually safe using plural names. Exceptions are DIAGNOSTICS, SCHEMAS, OCTETS, OFFSETS, OPTIONS, VALUES, PARAMETERS, PRIVILEGES and also verb-like words that also appear plural: OVERLAPS, READS, RETURNS, TRANSFORMS.
Many of us don't have the luxury of changing the field names. There, you'll need to know the details of the RDBM you're accessing:
For SQL Server use [square_braces] around the name. This works in an ODBC connection too.
For MySQL use `back_ticks`.
Postgres, Oracle and several other RDBMs will apparently allow "double_quotes" to be used.
Dotting the offending word onto the table name may also work.
You can put your column name in bracket like:
Select [from] from < ur_tablename>
Or
Put in a temprary table then use as you like.
Example:
Declare #temp_table table(temp_from varchar(max))
Insert into #temp_table
Select * from your_tablename
Here I just assume that your_tablename contains only one column (i.e. from).
In MySQL, alternatively to using back quotes (`), you can use the UI to alter column names. Right click the table > Alter table > Edit the column name that contains sql keyword > Commit.
select [from] from <table>
As a note, the above does not work in MySQL
Judging from the answers here and my own experience. The only acceptable answer, if you're planning on being portable is don't use SQL keywords for table, column, or other names.
All these answers work in the various databases but apparently a lot don't support the ANSI solution.
Simple solution
Lets say the column name is from ; So the column name in query can be referred by table alias
Select * from user u where u.from="US"
In Oracle SQL Developer, pl/sql you can do this with double quotes but if you use double quotes you must type the column names in upper case. For example, SELECT "FROM" FROM MY_TABLE
I have a schema in which a small number of the thousands of stored procedures have been created with quoted identifiers. I need to fix them. The only way I currently have of identifying them is by opening them up in SQLDeveloper, one at a time, and checking to see if the CREATE OR REPLACE... bit at the top has quotes around the procedure name. Does anyone have any cunning method of identifying these troublesome objects more easily? Have I overlooked some Oracle system view with a this_uses_quoted_identifiers flag, perhaps? Please enlighten me!
There are at least 2 ways:
select * from all_source where type = 'PROCEDURE' and line = 1 and text like '%"%'
and
select * from all_procedures where procedure_name != upper(procedure_name)
However, none of them is 100% correct and complete. The first one looks for any double quote in the first line. The second one would only find procedures with lower caps in their name which would mean that double quotes have been used.
As far as I know, if you quote an identifier, but all the letters are in capital form, it is just equivalent to non quoted identifier.
So you can select from ALL_OBJECTS to see which object names have names with non capital letters.
I have a little silly question. I have installed a PostgreSQL DB Server, but when I run query, there is a problem with column identifier without quotes. I don't know why the quotes around identifiers are needed. My query:
SELECT vc."CAR_ID"
FROM "VEL_CAR" vc, "VEL_DRIVER" vd, "VEL_DRIVER_CAR" vdc
WHERE vc."CAR_ID" = vdc."CAR_ID" and
vdc."DRIVER_ID" = vd."DRIVER_ID";
My practice from Oracle DB is not to use ". So in Oracle:
SELECT vc.CAR_ID
FROM VEL_CAR vc, VEL_DRIVER vd, VEL_DRIVER_CAR vdc
WHERE vc.CAR_ID = vdc.CAR_ID and
vdc.DRIVER_ID = vd.DRIVER_ID;
When I run this query without quotes in PostgreSQL it throws error about syntax:
ERROR: column vc.car_id does not exist
LINE 1: SELECT vc.CAR_ID
Do you know why?
--SOLVED--
Thank you, now I solved the problem! It was about table creation. I created table objects using pgAdminIII and i wrote table name and column names uppercased. pgAdminIII created query with quotas - because of the names was uppercased. So query had to be written with quotas.
When you create your tables using double quotes, column and table names become case sensitive. So "car_id" is a different name than "CAR_ID"
You need to create your tables without using double quotes, then the names are not case sensitive: car_id is the same as CAR_ID (note the missing quotes!)
See the manual for details:
http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
Edit:
Oracle behaves just the same way. The only difference is that Oracle stores names in upper case and Postgres stores them in lower case. But the behaviour when using quotes is identical.
From Postgres documentation :
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.)
Seems to me that the table vc does not have a column named car_id. Are you sure it is there? Do \d vel_car to see the structure of the table.
The quotes are optional and you can usually skip them.
I'm querying an oracle 9i database with:
SELECT * FROM table WHERE column LIKE '%' || ‘someText’ || '%' ESCAPE '\';
and it fails with the error "escape character must be character string of length 1" ( ORA-01425 error), while succeeding in an oracle express 10g database.
Making it a double backslash (ESCAPE '\\') solves the problem for the oracle 9i database, but generates instead the same ORA-01425 error for the 10g database.
I cannot edit the SQL since it's auto-generated via Telerik OpenAccess ORM.
The Linq code that leads to the SQL above is:
activity.Name.Contains.("someText")
I would like both databases to handle the ESCAPE '\'... Or instead, have another way of searching table items by their name or description.
Thanks in advance!
Not familiar with Linq but I'm a bit confused about where you're executing the query - are you just pasting the generated code into SQL*Plus running against two databases, where that behaviour can at least be explained?
If you are doing it in SQL*Plus, do a show escape in each environment; I suspect 9i will report escape "\" (hex 5c) while the 10g will report escape off. This might indicate that escape handling has previously been set up in the 9i instance but not in the (presumably more recent) 10g one.
If any of this has turned out to be relevant so far, try doing set escape \ in the 10g session and try the \\ version again. And in 9i try doing escape off and try the single-\ version there. Both should now work.
Assuming you're still with me, the next question is why 9i has that setting; there's probably a login.sql or glogin.sql file that's setting it automatically. You might be able to get that removed, as long as it won't affect anything else, to allow the generated code to run unaltered.
I don't think any of that will be relevant if you're going to be executing the code some other way; not sure if you're just testing and debugging the generated code in SQL*Plus and will eventually execute it elsewhere (lack of knowledge of Linq again), in which case this may be a transitory problem anyway.
I'm also not sure what you're actually escaping anyway...
Try:
SELECT * FROM TABLENAME
WHERE COLUMNNAME LIKE '\%' ESCAPE '\';
Generally ESCAPE symbol in LIKE used for allow search symbols '%' and '_'
you could avoid the backslash issue altogether. Try using the curly braces around the escaped characters instead.
http://download.oracle.com/docs/cd/B10500_01/text.920/a96518/cqspcl.htm
Does it fail for every input or just specific strings? The problem may not be with the query, but with the input. If there is an odd number of backslashes, Oracle may try to escape something that shouldn't need an escape.
For example, this works because it's escaping the '%':
select * from dual where 'test' like '%'||'\'||'%' escape '\';
But this fails because it's trying to escape 'a', which doesn't need escaping:
select * from dual where 'test' like '%'||'\a'||'%' escape '\';
Can you modify the string before it's passed to the function and fix odd backslashes?
In case anyone stops by with the same problem... My issue was that I was dealing with “NVARCHAR2” fields. I received help with this issue in the oracle forums :)
This query: select * from dual where 'dummy' like '%' escape '\';
works on both because the field ‘dummy’ is varchar2. If it were nvarchar2, the part of the query that could (only possibly!) cause problems would be the “escape '\'” part (my oracle 9i wants escape ‘\’, my oracle 10g wants ‘\\’).
To overcome the problem, instead of using the ORM’s autogenerated code, I have written a stored procedure (only when I’m searching for strings), where I handle nvarchar2 fields like this: where TableName.ColumnName like N'%' || ‘someText’ || N'%' escape N'\'
And it’s working fine :)
That doesn’t explain, however, how having the same NVARCHAR2 columns, and the same SQL queries, they were handled differently by the two oracle servers (the 10g express on my local PC and the 9i) – that remains a question. So for anyone running into similar problems, it may be good to know if it’s a nvarchar2 issue (I had no idea it could be a problem), and try working around it.
Quick question playing with PL SQL it seems that the tables column was named as the data type NUMBER so trying to perform a query fails since the column is being recognized as a datatype instead of a column name. Anyone know how to get around this without modifying the schema?
EDIT:
Thanks everyone for the help yeah the issue was it had to be in quotes and was case sensitive.
Place it between double quotes and the case of each character must match the case of the corresponding character in the column name exactly.
Try putting the column name in double quotes ("column_name")
Try wrapping a column name in single or double quotes.