Liquibase Remove identity from colunm - oracle

I want to execute te command below in Liquibase using yaml language in a oracle database, how can I do that ?
alter table MYTABLE modify MYCOLUNM drop identity;
I tried some like that ( without success )
databaseChangeLog:
- changeSet:
...
changes:
- modifyDataType:
columnName: MYCOLUNM
newDataType: number(9)
autoIncrement: false
tableName: MYTABLE
There isn't error and the autoIncrement persists.
The result is:
Liquibase command 'update' was executed successfully.

We don't have a change type for dropping an identity. The modifyDataType change doesn't try to modify whether it's an autoincrement or not, it focuses on the data type itself.
I created a bug for this issue here if you'd like to follow it: https://github.com/liquibase/liquibase/issues/3180
The solution for now is just to specify the SQL that you want directly.
databaseChangeLog:
- changeSet:
...
changes:
- sql:
sql: alter table MYTABLE modify MYCOLUNM drop identity;

Related

Doctrine 2 Symfony 5 migration to an oracle database

I have
PHP 8.0
Ubuntu 20.4 running in a VM
Symfony Version 5
doctrine/orm 2.8.2
doctrine/dbal 2.12.1
doctrine/migrations 3.1.1
and oracle19c running
I have also some entities which I want now to make:migrate with doctrine. But at this point I stuck on this error:
More information:
In doctrine.yaml:
dbal:
default_connection: oracle
connections:
default:
schema_filter: ~^(?!t_cmdb_|m_cmdb_|migration_versions)~
mapping_types:
enum: string
# configure these for your database server
url: '%env(resolve:DATABASE_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
oracle:
schema_filter: ~^(?!t_cmdb_|m_cmdb_|migration_versions)~
mapping_types:
enum: string
# configure these for your database server
url: '%env(resolve:DATABASE_CUSTOMER_URL)%'
servicename: 'pdb'
service: true
driver: 'oci8'
server_version: ~
charset: AL32UTF8
I have a oracle database created with:
php bin/console doctrine:database:create --connection oracle
which goes through without any problems
Than I call
php bin/console make:migration -vvv
I got this error message:
[Doctrine\DBAL\Exception]
Unknown database type interval day(3) to second(2) requested, Doctrine\DBAL\Platforms\OraclePlatform may not support it.
All my date columns have the type datetime there is no interval in there!
I have searched for this problem but I can't come through.
Did somebody has this Problem while making migration for doctrine?
Thanks a lot for any hint.
Michael
Doctrine commands usually scan all tables in the user/schema defined in Symfony's .env file (look for DATABASE_USER). That error means that at least one of the tables in that schema has a column of type "INTERVAL...".
If you are sure that you don't have any table with an "INTERVAL..." type column, it may be that you are using directly the SYSTEM user/schema (or any other Oracle reserved user/schema). In this case, you need to create a separate user/schema for your project and move your project tables there.
Anyway, run this to check which tables under which user/schema (OWNER) have a column of type "INTERVAL...":
SELECT
OWNER,
TABLE_NAME ,
COLUMN_NAME,
DATA_TYPE,
DATA_LENGTH,
DATA_PRECISION,
DATA_SCALE
FROM ALL_TAB_COLUMNS
where
data_type like 'INTERVAL%'
-- and OWNER = 'YOUR_USER_SCHEMA' -- must be in uppercase
ORDER BY TABLE_NAME
If you do use such a column type in your project, then you must add that column type in Doctrine's configuration: https://www.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/custom-mapping-types.html
If you discover that you were using the SYSTEM user/schema directly (perhaps in a Docker container?), then create your separate project user/schema:
CREATE USER your_separate_user_schema IDENTIFIED BY oracle; -- oracle is the password
Grant create session to your_separate_user_schema ; -- to be able to login with the new user
ALTER USER your_separate_user_schema quota unlimited on USERS; -- give your user schema disk space
To copy only the necessary tables from SYSTEM to your_separate_user_schema: while in system/sysdba, for each table do:
create table your_separate_user_schema.table_name as select * from table_name ;

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.

Trying to Create a temp table in Oracle

Getting an error message when trying to create a temp table. I copied this code directly from Oracle's website. I also downloaded the latest version 18.2. What am I missing here?
CREATE PRIVATE TEMPORARY TABLE ora$ptt_my_temp_table
(
id NUMBER(10,2),
description VARCHAR2(20)
)
ON COMMIT PRESERVE DEFINITION;
Error Message:
Error starting at line : 1 in command -
CREATE PRIVATE TEMPORARY TABLE ora$ptt_my_temp_table
(
id NUMBER(10,2),
description VARCHAR2(20)
)
ON COMMIT PRESERVE DEFINITION
Error report -
ORA-00905: missing keyword
00905. 00000 - "missing keyword"
*Cause:
*Action:
I presume you're not on Oracle 18c but some lower version (which doesn't know private temporary tables). Therefore, I suggest you run
CREATE GLOBAL TEMPORARY TABLE ora$ptt_my_temp_table
(
id NUMBER(10,2),
description VARCHAR2(20)
)
ON COMMIT PRESERVE ROWS;
and move on.
The problem is the ON COMMIT PRESERVE ROWS line. That syntax is only used for Global Temorary Tables. For Private Temporary tables, you need to use one of the following:
ON COMMIT DROP DEFINITION
This drops the table at the end of the transaction (or at the end of the session if transactions are not being used).
This is the default, so this line can be omitted if this is the behavior you want.
ON COMMIT PRESERVE DEFINITION
The table will persist beyond any transactions, but will still be deleted at the end of the session.
See: https://oracle-base.com/articles/18c/private-temporary-tables-18c

How to remove a default value in oracle [duplicate]

A column in a table has a default value of sysdate and I want to change it so it gets no default value, how do I do this?
ALTER TABLE YourTable MODIFY YourColumn DEFAULT NULL;
Joe's answer is correct in the sense that a column with DEFAULT NULL is functionally equivalent to having never defined a default value for that column in the first place: if a column has no default value, inserting a new row without specifying a value for that column results in NULL.
However, Oracle internally represents the two cases distinctly, as can be seen by looking at the ALL_TAB_COLUMNS system view. (This applies to Oracle 10.x, 11.x, and 12.x, and probably to older versions as well.)
The case where a column has been created, or ALTERed, with DEFAULT NULL:
create table foo (bar varchar2(3) default null);
select default_length, data_default from all_tab_columns where table_name='FOO';
=> default_length data_default
-------------- ------------
4 NULL
select dbms_metadata.get_ddl('TABLE','FOO') from dual;
=> CREATE TABLE "FOO"
( "BAR" VARCHAR(3) DEFAULT NULL
…
)
No default ever specified:
create table foo (bar varchar2(3));
select default_length, data_default from all_tab_columns where table_name='FOO';
=> default_length data_default
-------------- ------------
(null) (null)
select dbms_metadata.get_ddl('TABLE','FOO') from dual;
=> CREATE TABLE "FOO"
( "BAR" VARCHAR(3)
…
)
As shown above, there is an important case where this otherwise-meaningless distinction makes a difference in Oracle's output: when using DBMS_METADATA.GET_DDL() to extract the table definition.
If you are using GET_DDL() to introspect your database, then you will get slightly different DDL output for functionally-identical tables.
This is really quite annoying when using GET_DDL() for version control and comparison among multiple instances of a database, and there is no way to avoid it, other than to manually modify the output of GET_DDL(), or to completely recreate the table with no default value.
The only way to do what you want is to recreate the table.
It is pretty easy to do in Toad, just right click on the table and select "Rebuild Table". Toad will create script which will rename the table and recreate a new table. The script will recreate indexes, constraints, foreign keys, comments, etc... and populate the table with data.
Just modify the script to remove "default null" after the column in question.

hsqldb update on insert

Does anyone know of a solution to make HSQLDB update columns by calling INSERT. I would like my code to be able to insert, and if there's already data, to update that data. I know MySQl, I believe, has 'ON DUPLICATE KEY UPDATE'. I can't seem to find any recent documentation on this.
A good sample is sometimes better the formal documentation on MERGE statement :)
Sample 1
For a table (MY_TABLE) with tho columns (COL_A and COL_B), where the first column is a primary key:
MERGE INTO MY_TABLE AS t USING (VALUES(?,?)) AS vals(a,b)
ON t.COL_A=vals.a
WHEN MATCHED THEN UPDATE SET t.COL_B=vals.b
WHEN NOT MATCHED THEN INSERT VALUES vals.a, vals.b
Sample 2
Let's add another column (COL_C) to our table:
MERGE INTO MY_TABLE AS t USING (VALUES(?,?,?)) AS vals(a,b,c)
ON t.COL_A=vals.a
WHEN MATCHED THEN UPDATE SET t.COL_B=vals.b, t.COL_C=vals.c
WHEN NOT MATCHED THEN INSERT VALUES vals.a, vals.b, vals.c
Sample 3
Now let's change the primary key to consist of first two columns (COL_A and COL_B):
MERGE INTO MY_TABLE AS t USING (VALUES(?,?,?)) AS vals(a,b,c)
ON t.COL_A=vals.a AND t.COL_B=vals.b
WHEN MATCHED THEN UPDATE SET t.COL_C=vals.c
WHEN NOT MATCHED THEN INSERT VALUES vals.a, vals.b, vals.c
Enjoy!
HSQLDB provides the MERGE statement for this purpose.
http://hsqldb.org/doc/2.0/guide/dataaccess-chapt.html#dac_merge_statement
Alternatively, you can write a short stored procedure to insert, then catch any constraint violation exception and perform an update.
http://hsqldb.org/doc/2.0/guide/sqlroutines-chapt.html#src_psm_handlers
Update: From version 2.3.4 HSQLDB also supports the MySQL syntax for ON DUPLICATE KEY

Resources