ORMLite and Oracle - case sensitive column names - oracle

I have just started using ORMLite and was using at home to experiment on MySQL. Now I have decided to try using it on Oracle, but have noticed an issue with case sensitivity of column names.
When using the TableUtils.createTableIfNotExists() it appears to generate CREATE statements that wrap the table and column names in double quotes. For example:
CREATE TABLE "T_SUBURB" ("id" NUMERIC , "description" VARCHAR2(255)
NOT NULL , "gnaf" VARCHAR2(255) , PRIMARY KEY ("id") )
This means that when I am attempting to query the database in Oracle SQL Developer I have to use the double quotes to specify the table and column names. This doesn't seem to happen when using MySQL.
I must admit I am a SQL novice, however it doesn't seem natural to wrap every table or column name in double quotes when attempting to query them. Looking at the OracleDatabaseType implementation it would seem that the entity name is intentionally double quoted in this example.
Does anybody know of a way to turn this behaviour off?
I am currently running version 4.43 from maven-central and Oracle 11g. Cheers.

When using the TableUtils.createTableIfNotExists() it appears to generate CREATE statements that wrap the table and column names in double quotes.
That's correct. The challenge for ORMLite is that it has to protect against special characters or reserved-words as field and table names. Words like "index" or "create" might make fine field names but will cause invalid SQL.
However, according to my reading of the OracleDatabaseType is should be generating uppercase field names:
#Override
public boolean isEntityNamesMustBeUpCase() {
return true;
}
If your field is created as "description" then something is wrong. Does DESCRIPTION work instead? Is ORMLite generating your schema and using an Oracle JDBC URI? Something like:
jdbc:oracle:...
If you are not using a JDBC URI like that then ORMLite may not be using the Oracle database type to create your tables. If you need to force it to use Oracle, you can create your
ConnectionSource connectionSource =
new JdbcConnectionSource(databaseUrl, new OracleDatabaseType());
Hope this helps.

Related

How to create Oracle Spatial Index?

I am trying to create an Oracle Spatial index but seeing strange behavior.
I have a table in my schema as follows:
CREATE TABLE "Event" (
"EventID" NUMBER(32,0) GENERATED ALWAYS AS IDENTITY INCREMENT BY 1 START WITH 1 NOT NULL,
"Name" NVARCHAR2(30),
"Location" "SDO_GEOMETRY" NOT NULL,
CONSTRAINT "PK_EVENT" PRIMARY KEY ("EventID")
) ;
This works fine and I know I have to create an entry in user_sdo_geom_metadata, that works as you would expect with the following:
insert into user_sdo_geom_metadata (table_name,column_name,diminfo,srid) values ('Event','Location',
sdo_dim_array(sdo_dim_element('X',-180.0,180.0, 0.005),sdo_dim_element('Y',-90.0,90.0, 0.005)), 4326);
This reports success and when I do a select on user_sdo_geom_metadata I see the row. However, when I try to create the spatial index with:
CREATE INDEX "EVINDEX" ON "Event" ("Location") INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2
I get the following error:
SQL Error [29855] [99999]: ORA-29855: error occurred in the execution of ODCIINDEXCREATE routine
ORA-13203: failed to read USER_SDO_GEOM_METADATA view
ORA-13203: failed to read USER_SDO_GEOM_METADATA view
ORA-06512: at "MDSYS.SDO_INDEX_METHOD_10I", line 10
The weird thing is the Index looks like it's been created.
select * from all_indexes where table_name='Event';
Shows the index??? The other odd thing is when I do a select * on ALL_SDO_GEOM_METADATA, no rows are returned??? I'm connecting as a user with almost every privilege and role but not as SYSDBA. I can't get my head around this one.
UPDATE
Incredibly, this seems to be a case sensitivity issue. If you change the table and column names to all UPPERCASE it works. It seems my neverending disappointment in Oracle has a whole new chapter. Going to try to struggle through this somehow, but like most things with Oracle, it's one unrelenting slog to get anything done :(
The documentation says:
The table name cannot contain spaces or mixed-case letters in a quoted string when inserted into the USER_SDO_GEOM_METADATA view, and it cannot be in a quoted string when used in a query (unless it is in all uppercase characters).
and
The column name cannot contain spaces or mixed-case letters in a quoted string when inserted into the USER_SDO_GEOM_METADATA view, and it cannot be in a quoted string when used in a query (unless it is in all uppercase characters).
However, it also says:
All letters in the names are converted to uppercase before the names are stored in geometry metadata views or before the tables are accessed. This conversion also applies to any schema name specified with the table name.
which you can see if you query the user_sdo_geom_metadata view after your insert; the mixed-case names have become uppercase EVENT and LOCATION.
But then:
Note: Letter case conversion does not apply if you use mixed case (“CamelCase”) names enclosed in quotation marks. However, be aware that many experts recommend against using mixed-case names.
And indeed, rather unintuitively, it seems to work if you include the quotes in the user_sdo_geom_metadata insert:
insert into user_sdo_geom_metadata (table_name,column_name,diminfo,srid)
values (
'"Event"',
'"Location"',
sdo_dim_array(sdo_dim_element('X',-180.0,180.0, 0.005),
sdo_dim_element('Y',-90.0,90.0, 0.005)), 4326
);
db<>fiddle
So it appears that the values from the view are at some point concatenated into a dynamic SQL statement, which would explain some of the behaviour.

Cannot insert NULL into table

I'm using EF Core to connect to an Oracle11g database (using the Oracle.EntityFrameworkCore v2.19.90 provider). It's a code first scenario, the tables are created successfully and everything is as expected.
The problem is, when I try to insert something into the database, for example:
_context.Roles.Add(new ApplicationRole()
{
Name = "FOO",
DisplayName = "Foo"
});
_context.SaveChanges();
I get an error:
OracleException: ORA-01400: cannot insert NULL into ("SCHEMA"."AppRole"."Id")
The column Id is indeed non-nullable. When I use the SQL Server provider, everything is fine, the SQL Server automatically chooses an id for my entity.
Is there any way to get Oracle to set an Id for me? Or could it be done in another way?
I don't want to use Oracle triggers and the solution should be full code first.
As you're on Oracle 11g, then you have to use a trigger along with a sequence which will populate ID column in the background.
Another option is to, obviously, provide ID value during insert.
If you were on 12c or above, you could have used identity column. As you're not, your options are listed above.
One option may be usage of SEQUENCE and default value:
CREATE TABLE AppRole(
Id INT NOT NULL,
Name VARCHAR2(100),
DisplayName VARCHAR2(100)
);
CREATE SEQUENCE seq;
ALTER TABLE AppRole MODIFY Id DEFAULT seq.NEXTVAL;
INSERT INTO AppRole(Name, DisplayName) VALUES ('Foo','Foo');
db<>fiddle demo
Default with sequence is supported from Oracle 12c.
There should exist syntax in EntityFramework core that allow to do the following without relying on triggers(raw SQL query as last resort):
INSERT INTO AppRole(Id, Name, DisplayName) VALUES (seq.NextVal, 'Foo','Foo');
Sequences
Basic usage
You can set up a sequence in the model, and then use it to generate
values for properties: C#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasSequence<int>("OrderNumbers");
modelBuilder.Entity<Order>()
.Property(o => o.OrderNo)
.HasDefaultValueSql("NEXT VALUE FOR shared.OrderNumbers");
}
Note that the specific SQL used to generate a value from a sequence is
database-specific; the above example works on SQL Server but will fail
on other databases. Consult your specific database's documentation for
more information.
Oracle syntax is sequence_name.NEXTVAL.

how to specifically define table name in Oracle SQL

i have a DB which has a table named LIKE.
uppon trying to execute any query on the table, it gives me an error and i know it's because of the name which is trying to use the query keyword LIKE.
Now, i have "bypassed" this issue in MySQL by just selecting the table as
SELECT tk_oseba_id, COUNT(tk_tip_like_id) AS St_Like_haha
FROM student999.`like`;
Now this same line wont work at `l...is there any special way to to this in oracle or how can i manipulate with the table by not using the LIKE keyword.
Oracles's counter part to mysql's back tick is quote for defining tablenames/columns.
To use a key word as a table name though I recommend against it...
wrap the table name in quotes. From student9999."like"
AND... it forces case sensitivity when you use the quotes!

Why does "UPDATE Users SET Password=? WHERE Username=?" give a syntax error? [duplicate]

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

Oracle SQL Developer lowercase identifiers for migrated DBs?

I'm currently porting a Code Igniter based application from MySQL to Oracle (11g) for a specific client. Both the MySQL and Oracle back-ends have to work in conjunction (i.e. we cannot drop the one or the other).
The MySQL DB uses around 100 tables of which ALL identifiers are in lowercase. When I migrate this DB to Oracle, using Oracle's SQL Developer tool, I end up with a 'properly' converted DB, but... with all uppercase identifiers.
Now, for normal usage this isn't really a problem, but the issue arises when using the CI Active Record class. It generates queries to the effect of:
SELECT "somecolumn" FROM "sometable" WHERE "someothercolumn" = somevalue
The issue is that when the " quotes are used for these identifiers, Oracle forces these identifiers to be interpreted in a case sensitive way, which in this case is wreaking havoc.
Patching the core code of CI and/or the application to either make all queries use case insensitive identifiers (i.e. by dropping the usage of the " quotes around the identifiers) or to convert all identifiers to uppercase ones on the fly, is IMO not desired, as a potential future framework upgrade is then compromised. Renaming ALL MySQL identifiers to become in uppercase is also a very unattractive scenario and has an even bigger impact on the application itself -- not an option for sure.
Instead, what I would like to achieve, is to have the migration process (i.e. using SQL Developer) simply respecting the case of the source DB and to perform the conversion exactly as it does up to now, with the exception that the identifiers do not get changed to their uppercase version.
I have searched a fair deal online to find a way to achieve this, and so far it has been to no avail.
Does anyone know if this can be done, and if so: how?
Is the conversion to all uppercase identifiers by any chance a global DB setting, perhaps?
I would have assumed this to be a trivial thing, but I haven't been able to figure it out so far and what little related references that I did come across do not sound very promising...
If you can acquire a schema script created by the database migration all you need to do is change the identifiers ( tablenames, view names, column names etc ) to be surrounded with double quotation marks. (I'm not sure if SQL Developer migrations actually has the option to preserve the case).
Without the quote marks Oracle will assume all identifiers are case-insensitive. However this is stored internally as upper case strings in the data dictionary. By using quote marks will force Oracle to use the exact case for the schema objects.
eg.
create table Customers
(
Name varchar2(100),
CreationDate date not null
);
will create CUSTOMERS internally in the data-dictionar and you can write queries like:
select name, creationdate from customers;
alternatively:
create table "Customers"
(
"Name" varchar2(100),
"CreationDate" date not null
);
will create "Customers" internally. You can only write queries using quotes and exact case:
select "Name", "CreationDate" from "Customers";
I have hit this before and simply edited oci8_driver.php (../system/database/oci) as follows:
// The character used for excaping
var $_escape_char = '"';
to
// The character used for excaping
var $_escape_char = '';
Stewart

Resources