set locale on Oracle connection - oracle

In my company's product, we retrieve results a page at a time from the database. Because of this all filtering and sorting must be done on the database. One of the problems is coded values. For filtering and sorting to work properly, the code values need to be translated to locale specific labels in the query.
My plan is to use a table similar to the following:
t_code_to_label (
type varchar2(10),
locale varchar2(10),
code varchar2(10),
label varchar2(50)
)
The first three columns are the primary (unique) key.
When using this table, you would see something like this
select ent.name, ent.ent_type, entlabel.label as ent_type_label
from t_entitlements ent
join t_code_to_label entlabel on entlabel.type='entlabel' and entlabel.locale=currentLocale() and entlabel.code=ent.ent_type
The problem is that currentLocale() is something that I made up. How can I on the Java side of a JDBC connection do something to set the locale for the Connection object that I have that I can read on the Oracle side in a simple function. Ideally this is true locale support by Oracle but I can't find such a thing.
I am using Oracle 10g and 11g.

Are you talking about the NLS_LANGUAGE setting of the Oracle database? Would you (from the client side) like to dictate the usage of a particular NLS_LANGUAGE by Oracle database?
Then maybe this would work: Set Oracle NLS_LANGUAGE from java in a webapp
If you want an "all american" session you could do you could do something like:
ALTER SESSION SET NLS_LANGUAGE= 'AMERICAN' NLS_TERRITORY= 'AMERICA'
NLS_CURRENCY= '$' NLS_ISO_CURRENCY= 'AMERICA'
NLS_NUMERIC_CHARACTERS= '.,' NLS_CALENDAR= 'GREGORIAN'
NLS_DATE_FORMAT= 'DD-MON-RR' NLS_DATE_LANGUAGE= 'AMERICAN'
NLS_SORT= 'BINARY'

Related

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.

Oracle sqldveloper view date and tora difference

If I try a query as
select * from hr.employees
by sqldeveloper I have an output where the field HIRE_DATE is display so:
21-GIU-07
The data format is in according of the land (Italy)
If I use Tora or Toad (an old version) for the query the same row and the same field is display as
HIRE_DATE 2007-06-21 00:00:00
I am not undestand why there is time value in the field HIRE_DATE. In the example is 0 but I have found table where the time is set.
Why Tora/Toad show the time too and not in sqldeveloper ?
Thanks in advance anyone wants to answer
There is a parameter called NLS_DATE_FORMAT which specifies the default format for date data type.
The NLS_DATE_FORMAT has an order of overriding precedence, and tool specific NLS paramter settings will override it. That is the reason why two different tools has different outputs.
This is the most usual order of overriding precendence :
NLS_DATE_FORMAT is in the database initialization parameters, will be overriden by,
Settings of OS environment variable on the client machine, will be overriden by,
NLS parameter setting at session level with ALTER SESSION statements, will be overriden by,
to_date and to_char functions at the sql statement level.
Having said all that, in your situation, you need to check the NLS_DATE_FORMAT in both the tools.
Last but most important, check this link and learn more about the NLS_DATE_FORMAT.

Specify name of Oracle IDENTITY sequence?

I’m using Doctrine to connect to an Oracle database. At the moment I’m just testing locally.
However, when we move to production it seems there’s no way to specify the IDENTITY sequence name so it’s mirred in production and local. If they’re not the same it will make things quite difficult when testing before sending to production.
Is there any way to specify the Sequence name for the IDENTITY column?
Data_default column provides the default value (long) of this column. If you convert it to string (using dbms_output.put_line), you will get the name of the seqence.
select data_default
from all_tab_columns
where table_name ='<TABLE_NAME>'
and column_name='<COLUMN_NAME>';

Oracle SQL Developer client encoding

I read many of the related Stack Overflow's topics and I spent a whole day with googleing the following problem but I haven't found anything that would help, however the problem not seems to be complicated.
I have an Oracle database.
Let's see the following PL/SQL script:
CREATE TABLE Dummy(
id number(19,0),
tclob clob,
tnclob nclob,
PRIMARY KEY (id));
INSERT INTO dummy (id, tclob, tnclob) VALUES (1, 'ñ$ߤ*>;''<’', 'ñ$ߤ*>;''<’');
SELECT tclob, tnclob FROM dummy;
My problem is that 'ñ' and '’' characters are stored as a question mark.
I also tried to load the previously inserted values through JAVA, but I get the question marks instead of the special characters.
I created a small Java method which uses OraclePreparedStatement to save test data, and I use setNString() method to attach the nclob data to the query. In this case all characters are displayed fine in Java and also in SqlDeveloper.
So a possible solution is to use JAVA to save my data into the db. I have a thousands of lines SQL script which inserts data and I don't necessarily want to write the whole thing again in java.
So the question is: why the SqlDeveloper breaks the special characters?
My settings:
SELECT DECODE(parameter, 'NLS_CHARACTERSET', 'CHARACTER SET',
'NLS_LANGUAGE', 'LANGUAGE',
'NLS_TERRITORY', 'TERRITORY') name,
value from v$nls_parameters
WHERE parameter IN ( 'NLS_CHARACTERSET', 'NLS_LANGUAGE', 'NLS_TERRITORY')
Result:
+---------------+--------------+
| NAME | VALUE |
+---------------+--------------+
| LANGUAGE | HUNGARIAN |
| TERRITORY | HUNGARY |
| CHARACTER SET | EE8ISO8859P2 |
+---------------+--------------+
I changed SqlDeveloper/Preferences/Environment/Encoding to UTF-8.
I also changed HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraDb11g_home1 value to HUNGARIAN_HUNGARY.UTF8
Update: I tried to insert the data with the following syntaxes:
INSERT INTO dummy (id, tclob, tnclob) VALUES (1, N'ñ$ߤ*>;''<’', N'ñ$ߤ*>;''<’');
INSERT INTO dummy (id, tclob, tnclob) VALUES (1, 'ñ$ߤ*>;''<’', to_nclob('ñ$ߤ*>;''<’'));
Nothing helped.
So what can I do?
On the PC that PLSQL is installed, set the value of NLS_LANG registery entry equal to the PC's operation system locale (code page), equivalent value.
How to detect operating system language locale?
How to map OS locale to NLS_LANG value?
When using PLSQL the initial parameter of client-language that is required to create an Oracle session is read from NLS_LANG registry entry.
Due to Oracle documents, invalid data usually occurs in a database because the NLS_LANG parameter is not set properly on the client.
The NLS_LANG value should reflect the client operating system code page.
For example, in an English Windows environment, the code page is WE8MSWIN1252. When the NLS_LANG parameter is set properly, the database can automatically convert incoming data from the client operating system to its encoding.
When using JAVA method, the client-language parameter is set by the value from the Control Panel, under Regional and Language Options, so the things will be OK.
You can try to change NLS_LANG value on your Win PC with regedit tool.
Path is: \HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE, when NLS_LANG contain value of your Oracle client's current encoding.
There is Oracle's list of available encodings:
Commonly Used Values for NLS_LANG

Oracle, utf-8, NVARCHAR2, and a lot of confusion

I have the following "translation" table in an oracle 10g database:
ID VARCHAR2(100 BYTE)
LANGUAGE CHAR(2 BYTE)
COUNTRY CHAR(2 BYTE)
TRANSLATION NVARCHAR2(2000 CHAR)
TRACK_TIMESTAMP DATE
TRACK_USER VARCHAR2(2000 BYTE)
When I try to do this:
update translation set translation = 'œ' where id = 'MY_ID' And language = 'fr';
Then I run this:
select * from translation where id = 'MY_ID' and language = 'fr';
and the translation column shows: S instead of œ and I have no idea why.
Due to legacy issues I cannot convert the whole database to use UTF-8, are there any other options?
Currently the national character set is AL16UTF16. The ordinary character set is WE8ISO8859P1.
I am currently using java 1.6
The above is a simplified example. Here is what the query looks like in my actual application:
UPDATE TRANSLATION SET TRANSLATION=? WHERE TRANSLATION.COUNTRY=? and TRANSLATION.ID=? and TRANSLATION.LANGUAGE=? 1=1,800 - 2,500 œufs par heure 2=CA 3=3_XT_FE_ECS18 4=fr
The problem here is instead of adding œufs it adds ¿ufs
Since you are using bind variables rather than hard-coded literals, you should be able to pass Unicode strings to your UPDATE statement.
If you were using straight JDBC to write to the database, there is an example in the JDBC Developer's Guide on writing data to a NVARCHAR2 column. If you are using a 1.5 JVM, it is necessary to use the OraclePreparedStatement.setFormOfUse call for each NVARCHAR2 column. In a 1.6 JVM, life gets easier because JDBC 4.0 added NCHAR and NVARCHAR2 types. If you are using a 1.5 JVM, getting an ORM framework like Spring to use the Oracle extensions to JDBC may be a non-trivial undertaking. I'm not familiar enough with Spring to know what steps would be necessary for that to happen.
Potentially, you may be able to modify the connection string to specify defaultNChar=true. That will force the driver to treat all character columns using the national character set. That may be enough to resolve your problem without getting Spring to use the OraclePreparedStatement extensions.

Resources