SQLSTATE[23505]: Unique violation In-spite of ID set to auto_increment - laravel

I have created migration from the PHP artisan command and it had created a table in my Postgres database, with id set to auto_increment.
I have made some seeder in laravel and three rows of data are fed to the previously created table through php artisan db:seed command.
When I am inserting data through some form in the same table, it is giving me an error.
error:SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates unique constraint "roles_pkey" DETAIL: Key (id)=(1) already exists. (SQL: insert into "roles" ("name", "guard_name", "updated_at", "created_at") values (staff, web, 2019-07-03 07:38:37, 2019-07-03 07:38:37) returning "id")

Sequences are objects that return a value that is one greater on each request, regardless of which transaction it was called on. A sequence by default starts at 1 and can be applied to a table, or many tables, so it cannot know how many values there are in your table already. If you want your insert to work you will need to manually set it.
SELECT setval('roles_id_seq', (SELECT coalesce((SELECT max(id) from roles),1)))
This query is assuming that the sequence used was created on the column "id" on the "roles" table, if not the sequence name can be found by checking that columns DDL e.g. NOT NULL DEFAULT setval('the_sequence_name') and use that to set the value.

Related

Raw query to set AutoIncrement to false?

The id column in the student table is an auto incrementing one.I wanted to make that to non - autoincrementing. May i know, how can i modify the below query to work as such?
DB::statement("ALTER TABLE student SET AUTO_INCREMENT=FALSE;");
the above code shows the below error.
Illuminate\Database\QueryException
SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "AUTO_INCREMENT"
LINE 1: ALTER TABLE student SET AUTO_INCREMENT=FALSE;
^ (SQL: ALTER TABLE student SET AUTO_INCREMENT=FALSE;)
The correct syntax in PostgreSQL would be:
ALTER TABLE student ALTER COLUMN id DROP DEFAULT;
Where id is the serial column.
You might also want to drop the not null constraint :
ALTER TABLE student ALTER COLUMN id DROP NOT NULL;
This is an example of why posting table definitions (ddl) and Postgres version can be critical. #Zakaria is correct if the Postgres version is prior to version 10, or if version 10 or later and is still defined as serial/bigserial. However the preferred definition for version 10 and later is generated always as identity. If defined as identity you need:
alter table student alter column id drop identity.
I would not drop a not null constraint, and if it is the PK it is moot point as it will automatically be not null.

Laravel firstOrCreate method throws duplicate ID error

I am in the midst of writing a command in my Laravel project which inserts categories to a database table, but depending on whether or not they already exist.
I investigated the way to do this and came across firstOrCreate method, so I wrote the following in my command:
$comCats = new CommunicationsCategories();
$comCats->firstOrCreate(
['name' => 'Job Updates'], ['region_id' => 1]);
$comCats->firstOrCreate(
['name' => 'Alerts'], ['region_id' => 1]);
Basically, I need to create these two categories in the communications_categories table with a region ID of 1. The Job Updates category already exists, so it skipped that as expected but when it tries to create the Alerts category which doesn't exist I get the following error in my console:
SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value
violates unique constraint "communications_categories_pkey"
DETAIL: Key (id)=(2) already exists. (SQL: insert into
"communications_categories" ("name", "region_id", "updated_at",
"created_at") values (Alerts, 1, 2018-06-19 09:38:20, 2018-06-19
09:38:20) returning "id")
It appears that it's trying to allocate a primary key ID of 2 when it already exists - but the table structure has a nextval on the primary key which I thought would take the last ID added and create a new one after that. According to the Laravel documentation on Eloquent Inserts here there's no mention of having to stipulate the actual primary key id itself, and the fillable elements are only name and region_id.
Any help on this appreciated, as I'm reasonably new to Laravel and the eloqent database methods. If it helps, I'm using a PostgreSQL database.
The other answer seems to have assumed that you need to have firstOrCreate explained to you, when in fact you have actually encountered a bug in the Laravel framework and also assumed that Key (id)=(2) refers to region_id instead of your autoincrementing primary key id.
You most likely want a unique index on communications_categories.name.
You can instead use this SQL in postgres (assuming you have a unique index on name) which should be more reliable than firstOrCreate, but if you were planning to use other laravel features with firstOrCreate (like observers, or more query builders), their functionality could be lost.
INSERT INTO communications_categories (name, region_id, created_at, updated_at)
VALUES ('Job Updates', 1, NOW(), NOW())
ON CONFLICT (name) DO
UPDATE SET region_id = excluded.region_id,
updated_at = NOW()
RETURNING *;
which can be used like:
$values = DB::select($sql); // will return Array of StdClass
or without returning * if you don't need the id values.
DB::insert($sql); // will return true
If you need the Eloquent object returned, I would recommend including returning * or returning id and passing that to CommunicationsCategories::findOrFail($values[0]['id']). Putting that complicated insert statement into an Eloquent select will probably be a lot of work. Eloquent also has a function called hydrate which could work without additional SQL calls.
The SQL statement will insert the desired values, except when there is a conflict on the unique constraint, then which it will apply the values excluded by conflict from insert to the pre-existing rows via an update.
The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the attributes from the first parameter, along with those in the optional second parameter.
$comCats->firstOrCreate(
['name' => 'Job Updates'], ['region_id' => 1]);
here you are trying to locate first a name with "Job Updates" and a region_id with 1 ,if laravel cant find the specific data, it will try to create or insert the given parameters, but when the system tries to insert, region_id with value of "1" already exist.
if region_id is your primary key try:
$comCats->firstOrCreate(
['name' => 'Job Updates']);
Pardon me for I cannot post a comment yet...
If somebody encounter this same issue about postgresql, this is definitely a bug. In my case this bug occurred after I imported a local postgresql database using heroku following this procedure:
Workaround for pushing to heroku database on windows machince.
I tried running the query again and it worked... it fails sometimes too. Now this sucks. I'll update this I found another way around this issue.
Edit:
After looking at more searches about the issue, I found the following which perfectly matches my situation:
PostgreSQL: Unique violation: 7 ERROR: duplicate key value violates unique constraint “users_pkey”

Can we create a function based primary key in Oracle 10?

There is a requirement in our application to create the unique primary key which depend on the value of another unique column (ERROR_CODE). But our application is in a geo active active environment (have several active databases which are synchronized using another program).
Therefore even-though we have a unique constraint on this ERROR_CODE field, there is a possibility that each database has a row with a different PK for the same ERROR_CODE. During the database synchronization, this is a problem, because there are some child tables which has the PK stored in one DB and other rows contain the PK stored in other DB. Because of the unique constraint of ERROR_CODE, sync process cannot move both rows to each database (which is also not a good thing to do).
So there is a suggestion to use the hash of the ERROR_CODE field as the PK value.
I would like to know whether we can define a function based Primary key in oracle?
If PK field is "ID",
"ID" should be equal to ora_has(ERROR_CODE).
Is it possible to define the primary key like that in oracle?
In Oracle 10 you cannot do this, but in Oracle 11 you can. You have to create a virtual column, such columns can be used also as primary key:
ALTER TABLE MY_TABLE ADD (ID NUMBER GENERATED ALWAYS AS (ora_has(ERROR_CODE)) VIRTUAL);
ALTER TABLE MY_TABLE ADD CONSTRAINT t_test_pk PRIMARY KEY (ID) USING INDEX;

H2: Adding a NOT NULL column to a table with records

I'd like to add a NOT NULL column to a table called server. Problem is, the table already contains records. When I invoke ALTER TABLE server ADD COLUMN full_discovery_duration BIGINT NOT NULL H2 complains that full_discovery_duration may not be null. I can work around the problem by specifying DEFAULT 0 but I don't want a default valuefor future inserts. What am I supposed to do?
Should I add the column with a default and then remove DEFAULT 0 from the column definition in a subsequent statement? Is there a better way?
You can first add the column with a default value, and then set the default to null. Getting rid of the default definition is not possible however as far as I know.
An alternative is to first allow null, then set the values, and later not allow nulls.
drop table server;
create table server(id int);
insert into server values(1);
alter table server
add column
full_discovery_duration bigint;
update server set full_discovery_duration = 0;
alter table server
alter column
full_discovery_duration set not null;
While adding columns to existing tables, it should either be a nullable column or a default value must be specified. And what do you mean by removing the default? how can you remove value from a not null column?

Unique constraint violation during insert: why? (Oracle)

I'm trying to create a new row in a table. There are two constraints on the table -- one is on the key field (DB_ID), the other constrains a value to be one of several the the field ENV. When I do an insert, I do not include the key field as one of the fields I'm trying to insert, yet I'm getting this error:
unique constraint (N390.PK_DB_ID) violated
Here's the SQL that causes the error:
insert into cmdb_db
(narrative_name, db_name, db_type, schema, node, env, server_id, state, path)
values
('Test Database', 'DB', 'TYPE', 'SCH', '', 'SB01', 381, 'TEST', '')
The only thing I've been able to turn up is the possibility that Oracle might be trying to assign an already in-use DB_ID if rows were inserted manually. The data in this database was somehow restored/moved from a production database, but I don't have the details as to how that was done.
Any thoughts?
Presumably, since you're not providing a value for the DB_ID column, that value is being populated by a row-level before insert trigger defined on the table. That trigger, presumably, is selecting the value from a sequence.
Since the data was moved (presumably recently) from the production database, my wager would be that when the data was copied, the sequence was not modified as well. I would guess that the sequence is generating values that are much lower than the largest DB_ID that is currently in the table leading to the error.
You could confirm this suspicion by looking at the trigger to determine which sequence is being used and doing a
SELECT <<sequence name>>.nextval
FROM dual
and comparing that to
SELECT MAX(db_id)
FROM cmdb_db
If, as I suspect, the sequence is generating values that already exist in the database, you could increment the sequence until it was generating unused values or you could alter it to set the INCREMENT to something very large, get the nextval once, and set the INCREMENT back to 1.
Your error looks like you are duplicating an already existing Primary Key in your DB. You should modify your sql code to implement its own primary key by using something like the IDENTITY keyword.
CREATE TABLE [DB] (
[DBId] bigint NOT NULL IDENTITY,
...
CONSTRAINT [DB_PK] PRIMARY KEY ([DB] ASC),
);
It looks like you are not providing a value for the primary key field DB_ID. If that is a primary key, you must provide a unique value for that column. The only way not to provide it would be to create a database trigger that, on insert, would provide a value, most likely derived from a sequence.
If this is a restoration from another database and there is a sequence on this new instance, it might be trying to reuse a value. If the old data had unique keys from 1 - 1000 and your current sequence is at 500, it would be generating values that already exist. If a sequence does exist for this table and it is trying to use it, you would need to reconcile the values in your table with the current value of the sequence.
You can use SEQUENCE_NAME.CURRVAL to see the current value of the sequence (if it exists of course)

Resources