A primary key in ORACLE 11g became nullable - oracle11g

I have a table named 'ROUTE'. What "desc ROUTE" does is as follow:
Name Null Type
-------------------- ---- --------------
ROUTE_GUID RAW(16 BYTE)
LINE_GUID RAW(16 BYTE)
EVENT_GUID RAW(16 BYTE)
DESCRIPTION VARCHAR2(254)
Where ROUTE_GUID IS PK. When I tried altering the table, it showed "ORA-01442: column to be modified to NOT NULL is already NOT NULL". The real problem is that a .NET application has to use this table but it cannot unless a non-nullable column is found. There are also many database views associated with this table so that these view cannot be retrieved by .NET as well. Anyone got the same problem?

I came across this issue in Oracle 12g r 2. The desc MY_TABLE did not show the NOT NULL for a column that did have a NOT NULL constraint. Querying the DBA_TAB_COLS table for the NULLABLE column did not show it either. If I queried the DBA_CONS_COLUMNS and
DBA_CONSTRAINTS it did show up! The web site https://logic.edchen.org/how-to-resolve-ora-01442-column-to-be-modified-to-not-null-is-already-not-null/ almost helps; it showed the case where the constraint was in DISABLED status; my situation, the status was ENABLED. I just did a disable followed by an enable, and it worked; the NOT NULL is displayed now.
Code to display NOT NULL constraint name:
select a.constraint_name, b.status
from dba_cons_columns a
inner join dba_constraints b
on a.constraint_name = b.constraint_name
where a.table_name = 'MY_TABLE'
and a.owner = 'SCOTT' and a.owner=b.owner
and a.column_name = 'USER_NAME'
and b.constraint_type = 'C' and search_condition_vc like '%NOT NULL';
Code to disable and enable constraint:
alter table scott.my_table modify constraint SYS_C0019940 DISable;
alter table scott.my_table modify constraint SYS_C0019940 ENable;

Related

UPDATE table SET column=DEFAULT not working

What is the correct way to UPDATE a column to the DEFAULT value?
The documentation suggests that it can be used only in INSERT statements.
drop table if exists testjulian;
create table testjulian(
jul REAL NOT NULL DEFAULT ( julianday('now'))
,whatever STRING);
insert into testJulian values(null,"a"); --null not allowed
insert into testJulian(whatever) values("b"); --default value is used
update testjulian set jul= DEFAULT ; --syntax error
update testjulian set jul= NULL ; --null not allowed
The DEFAULT keyword is limited to being used when creating a table and it is designed for when inserting.
It cannot be used for an update, hence the syntax error.
In your case you could use :-
update testjulian set jul = julianday('now');
Or if you really wanted to dynamically get the DEFAULT value you could extract it from the sql column of sqlite_master.
e.g. using
SELECT sql FROM sqlite_master WHERE name = 'testjulian';
gives you :-
CREATE TABLE testjulian(jul REAL NOT NULL DEFAULT (
julianday('now')),whatever STRING)

MariaDB - Foreign key constraint incorrect?

I tried to re-engineer a database, that I use at work. The one at work is MS Access. At home, it's MariaDB. For convenience, I use MySQL Workbench.
When sending the complete SQL dump to the server, I get an error concerning some foreign key not being correctly formed. I guess, it is a minor mistake, but still I cannot find it.
My InnoDB status tells me this:
LATEST FOREIGN KEY ERROR
2018-10-03 00:18:29 409c7450 Error in foreign key constraint of table `mydb`.`IF`:
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblBelegPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tblBelege_tblECKassenschnittPositionen10`
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblECKassenschnittPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
Create table '`mydb`.`IF`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near '
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblBelegPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tblBelege_tblECKassenschnittPositionen10`
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblECKassenschnittPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB'.
The really weird thing is that I do not have any table named "IF"...
Can anyone make heads or tails of this for me? That would be very much appreciated.
-- Table `mydb`.`tblBelegPositionen`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`tblBelegPositionen` ;
SHOW WARNINGS;
CREATE TABLE IF NOT EXISTS `mydb`.`tblBelegPositionen` (
`belegposid` INT NOT NULL AUTO_INCREMENT,
`belegposBetrag` DOUBLE NOT NULL,
`zahlartfID` INT NOT NULL,
`belegfID` INT NOT NULL,
PRIMARY KEY (`belegposid`))
ENGINE = InnoDB;
SHOW WARNINGS;
-- Table `mydb`.`tblECKassenschnittPositionen`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`tblECKassenschnittPositionen` ;
SHOW WARNINGS;
CREATE TABLE IF NOT EXISTS `mydb`.`tblECKassenschnittPositionen` (
`ecposid` INT NOT NULL AUTO_INCREMENT,
`belegfID` INT NOT NULL,
`ecposBetrag` DOUBLE NOT NULL,
`kassenschnittfID` INT NOT NULL,
PRIMARY KEY (`ecposid`))
ENGINE = InnoDB;
SHOW WARNINGS;
-- Table `mydb`.`tblBelege`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`tblBelege` ;
SHOW WARNINGS;
CREATE TABLE IF NOT EXISTS `mydb`.`tblBelege` (
`belegid` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`belegKassierer` INT NOT NULL,
`belegDatum` DATETIME NOT NULL,
`kassefID` INT NOT NULL,
`belegSchicht` INT NULL,
`gvfID` INT NOT NULL,
`belegJahr` YEAR NULL,
`belegDruckErfolgt` TINYINT(1) NULL,
`belegDruckDatum` DATETIME NULL,
`belegPeriodenfremdeBuchung` TINYINT(1) NULL,
PRIMARY KEY (`belegid`, `gvfID`, `kassefID`),
CONSTRAINT `fk_tblBelege_tblBelegPositionen10`
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblBelegPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tblBelege_tblECKassenschnittPositionen10`
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblECKassenschnittPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SHOW WARNINGS;
Ok, so there are a couple of things to know here, as there were a couple of errors. You must check all the items that the error mentions, for correctness, to avoid trouble.
The cannot find an index in the referenced table portion of the error message means that the column/field specified in the REFERENCES clause must be indexed in the other table.
Then, the column type definition of the column specified in the FOREIGN KEY clause must match the column type of the column specified in the REFERENCES clause too, so even though the first item corrects part of the problem, there will still be an error related to another portion of the message: ...or column types in the table and the referenced table do not match.
So, to fix item 1, run these 2 queries:
ALTER TABLE `tblbelegpositionen` ADD INDEX(`belegfID`);
ALTER TABLE `tbleckassenschnittpositionen` ADD INDEX(`belegfID`);
Then to fix item 2, I had to change the first column of table tblBelege
from this:
`belegid` INT UNSIGNED NOT NULL AUTO_INCREMENT,
to this:
`belegid` INT NOT NULL,
...so that they matched the same type as the belegfID column as defined in the other tables. After those two changes, I was able to successfully run your CREATE TABLE `tblBelege` statement.
So, to recap:
Run your create table statements for tblbelegpositionen and
tbleckassenschnittpositionen.
Then run the 2 ALTER statements shown above for item 1.
Modify the first column of table tblBelege to match the column types as defined to belegfID in the other tables for item 2.
Then run your modified CREATE TABLE statement (with the item 2 change applied) to create the tblBelege table.
I'm a little confused about the same FOREIGN KEY referencing 2 different tables, but if it works for you, then ok. (not saying that it cannot be done, I've never used a foreign key that way) Perhaps you meant the opposite, to have a foreign key in the other 2 tables (1 in each table) that refer to tblBelege instead? If so, then you could add unsigned to the type definition for belegfID and it would work, and would not need the change that I mentioned with item 2.
Oh, and after you run the ALTER statements, you can view the table structure by running:
SHOW CREATE TABLE `tblbelegpositionen`;
SHOW CREATE TABLE `tbleckassenschnittpositionen`;
...to get the KEY definition that was added to include with your CREATE TABLE statements. Since they both create the same key, you really only need to run one of those statements and then add the KEY definition to both table statements.

setting default value while creating table in SQLite

I am working on SQLite. I want to create a table namely user_role with two column role_id and role_name. And there is an another table namely default that contain role_name and default_val.
I want to set Default value of role_id in the time of creating the table user_role and the Default value have to be retrieved from the table default.
I am new to SQLite and have to idea about the way to doing such recursive query. Please help.
The documentation says:
An explicit DEFAULT clause may specify that the default value is NULL, a string constant, a blob constant, a signed-number, or any constant expression enclosed in parentheses.
You would need to use a subquery, which is not allowed.
However, you could use a trigger that sets the ID if none was specified:
CREATE TRIGGER user_role_id_default
AFTER INSERT ON user_role
FOR EACH ROW
WHEN NEW.role_id IS NULL
BEGIN
UPDATE user_role
SET role_id = (SELECT default_val
FROM "default"
WHERE role_name = NEW.role_name)
WHERE rowid = NEW.rowid;
END;

Modify a column to NULL - Oracle

I have a table named CUSTOMER, with few columns. One of them is Customer_ID.
Initially Customer_ID column WILL NOT accept NULL values.
I've made some changes from code level, so that Customer_ID column will accept NULL values by default.
Now my requirement is that, I need to again make this column to accept NULL values.
For this I've added executing the below query:
ALTER TABLE Customer MODIFY Customer_ID nvarchar2(20) NULL
I'm getting the following error:
ORA-01451 error, the column already allows null entries so
therefore cannot be modified
This is because already I've made the Customer_ID column to accept NULL values.
Is there a way to check if the column will accept NULL values before executing the above query...??
You can use the column NULLABLE in USER_TAB_COLUMNS. This tells you whether the column allows nulls using a binary Y/N flag.
If you wanted to put this in a script you could do something like:
declare
l_null user_tab_columns.nullable%type;
begin
select nullable into l_null
from user_tab_columns
where table_name = 'CUSTOMER'
and column_name = 'CUSTOMER_ID';
if l_null = 'N' then
execute immediate 'ALTER TABLE Customer
MODIFY (Customer_ID nvarchar2(20) NULL)';
end if;
end;
It's best not to use dynamic SQL in order to alter tables. Do it manually and be sure to double check everything first.
Or you can just ignore the error:
declare
already_null exception;
pragma exception_init (already_null , -01451);
begin
execute immediate 'alter table <TABLE> modify(<COLUMN> null)';
exception when already_null then null;
end;
/
You might encounter this error when you have previously provided a DEFAULT ON NULL value for the NOT NULL column.
If this is the case, to make the column nullable, you must also reset its default value to NULL when you modify its nullability constraint.
eg:
DEFINE table_name = your_table_name_here
DEFINE column_name = your_column_name_here;
ALTER TABLE &table_name
MODIFY (
&column_name
DEFAULT NULL
NULL
);
I did something like this, it worked fine.
Try to execute query, if any error occurs, catch SQLException.
try {
stmt.execute("ALTER TABLE Customer MODIFY Customer_ID nvarchar2(20) NULL");
} catch (SQLException sqe) {
Logger("Column to be modified to NULL is already NULL : " + sqe);
}
Is this correct way of doing?
To modify the constraints of an existing table
for example... add not null constraint to a column.
Then follow the given steps:
1) Select the table in which you want to modify changes.
2) Click on Actions.. ---> select column ----> add.
3) Now give the column name, datatype, size, etc. and click ok.
4) You will see that the column is added to the table.
5) Now click on Edit button lying on the left side of Actions button.
6) Then you will get various table modifying options.
7) Select the column from the list.
8) Select the particular column in which you want to give not null.
9) Select Cannot be null from column properties.
10) That's it.

INSERT IF NOT EXISTS ELSE UPDATE?

I've found a few "would be" solutions for the classic "How do I insert a new record or update one if it already exists" but I cannot get any of them to work in SQLite.
I have a table defined as follows:
CREATE TABLE Book
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name VARCHAR(60) UNIQUE,
TypeID INTEGER,
Level INTEGER,
Seen INTEGER
What I want to do is add a record with a unique Name. If the Name already exists, I want to modify the fields.
Can somebody tell me how to do this please?
Have a look at http://sqlite.org/lang_conflict.html.
You want something like:
insert or replace into Book (ID, Name, TypeID, Level, Seen) values
((select ID from Book where Name = "SearchName"), "SearchName", ...);
Note that any field not in the insert list will be set to NULL if the row already exists in the table. This is why there's a subselect for the ID column: In the replacement case the statement would set it to NULL and then a fresh ID would be allocated.
This approach can also be used if you want to leave particular field values alone if the row in the replacement case but set the field to NULL in the insert case.
For example, assuming you want to leave Seen alone:
insert or replace into Book (ID, Name, TypeID, Level, Seen) values (
(select ID from Book where Name = "SearchName"),
"SearchName",
5,
6,
(select Seen from Book where Name = "SearchName"));
You should use the INSERT OR IGNORE command followed by an UPDATE command:
In the following example name is a primary key:
INSERT OR IGNORE INTO my_table (name, age) VALUES ('Karen', 34)
UPDATE my_table SET age = 34 WHERE name='Karen'
The first command will insert the record. If the record exists, it will ignore the error caused by the conflict with an existing primary key.
The second command will update the record (which now definitely exists)
You need to set a constraint on the table to trigger a "conflict" which you then resolve by doing a replace:
CREATE TABLE data (id INTEGER PRIMARY KEY, event_id INTEGER, track_id INTEGER, value REAL);
CREATE UNIQUE INDEX data_idx ON data(event_id, track_id);
Then you can issue:
INSERT OR REPLACE INTO data VALUES (NULL, 1, 2, 3);
INSERT OR REPLACE INTO data VALUES (NULL, 2, 2, 3);
INSERT OR REPLACE INTO data VALUES (NULL, 1, 2, 5);
The "SELECT * FROM data" will give you:
2|2|2|3.0
3|1|2|5.0
Note that the data.id is "3" and not "1" because REPLACE does a DELETE and INSERT, not an UPDATE. This also means that you must ensure that you define all necessary columns or you will get unexpected NULL values.
INSERT OR REPLACE will replace the other fields to default value.
sqlite> CREATE TABLE Book (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT,
TypeID INTEGER,
Level INTEGER,
Seen INTEGER
);
sqlite> INSERT INTO Book VALUES (1001, 'C++', 10, 10, 0);
sqlite> SELECT * FROM Book;
1001|C++|10|10|0
sqlite> INSERT OR REPLACE INTO Book(ID, Name) VALUES(1001, 'SQLite');
sqlite> SELECT * FROM Book;
1001|SQLite|||
If you want to preserve the other field
Method 1
sqlite> SELECT * FROM Book;
1001|C++|10|10|0
sqlite> INSERT OR IGNORE INTO Book(ID) VALUES(1001);
sqlite> UPDATE Book SET Name='SQLite' WHERE ID=1001;
sqlite> SELECT * FROM Book;
1001|SQLite|10|10|0
Method 2
Using UPSERT (syntax was added to SQLite with version 3.24.0 (2018-06-04))
INSERT INTO Book (ID, Name)
VALUES (1001, 'SQLite')
ON CONFLICT (ID) DO
UPDATE SET Name=excluded.Name;
The excluded. prefix equal to the value in VALUES ('SQLite').
Firstly update it. If affected row count = 0 then insert it. Its the easiest and suitable for all RDBMS.
Upsert is what you want. UPSERT syntax was added to SQLite with version 3.24.0 (2018-06-04).
CREATE TABLE phonebook2(
name TEXT PRIMARY KEY,
phonenumber TEXT,
validDate DATE
);
INSERT INTO phonebook2(name,phonenumber,validDate)
VALUES('Alice','704-555-1212','2018-05-08')
ON CONFLICT(name) DO UPDATE SET
phonenumber=excluded.phonenumber,
validDate=excluded.validDate
WHERE excluded.validDate>phonebook2.validDate;
Be warned that at this point the actual word "UPSERT" is not part of the upsert syntax.
The correct syntax is
INSERT INTO ... ON CONFLICT(...) DO UPDATE SET...
and if you are doing INSERT INTO SELECT ... your select needs at least WHERE true to solve parser ambiguity about the token ON with the join syntax.
Be warned that INSERT OR REPLACE... will delete the record before inserting a new one if it has to replace, which could be bad if you have foreign key cascades or other delete triggers.
If you have no primary key, You can insert if not exist, then do an update. The table must contain at least one entry before using this.
INSERT INTO Test
(id, name)
SELECT
101 as id,
'Bob' as name
FROM Test
WHERE NOT EXISTS(SELECT * FROM Test WHERE id = 101 and name = 'Bob') LIMIT 1;
Update Test SET id='101' WHERE name='Bob';
I believe you want UPSERT.
"INSERT OR REPLACE" without the additional trickery in that answer will reset any fields you don't specify to NULL or other default value. (This behavior of INSERT OR REPLACE is unlike UPDATE; it's exactly like INSERT, because it actually is INSERT; however if what you wanted is UPDATE-if-exists you probably want the UPDATE semantics and will be unpleasantly surprised by the actual result.)
The trickery from the suggested UPSERT implementation is basically to use INSERT OR REPLACE, but specify all fields, using embedded SELECT clauses to retrieve the current value for fields you don't want to change.
I think it's worth pointing out that there can be some unexpected behaviour here if you don't thoroughly understand how PRIMARY KEY and UNIQUE interact.
As an example, if you want to insert a record only if the NAME field isn't currently taken, and if it is, you want a constraint exception to fire to tell you, then INSERT OR REPLACE will not throw and exception and instead will resolve the UNIQUE constraint itself by replacing the conflicting record (the existing record with the same NAME). Gaspard's demonstrates this really well in his answer above.
If you want a constraint exception to fire, you have to use an INSERT statement, and rely on a separate UPDATE command to update the record once you know the name isn't taken.

Resources