I have a table like this:
CREATE TABLE Car
(
CarID INT NOT NULL AUTO_INCREMENT ,
CarBrand VARCHAR(20) NOT NULL ,
InsuranceNumber INT NOT NULL ,
PRIMARY KEY (CarID))AUTO_INCREMENT=1;
I want InsuranceNumber auto incremented just like CarID but
I know there cannot be 2 auto incremented columns at the same time but I did some research and found out that I can do this with creating a
trigger. I did tried my own but I couldn't manage to do what I want to.
I did tried something like this:
CREATE TRIGGER car_trigger AFTER INSERT ON Car
FOR EACH ROW UPDATE Car SET Car.CarID = Car.InsuranceNumber
But I get a syntax error. What should I do ?
The issue you asked about is a syntax error in your trigger code.
The solution is to use the special keyword NEW instead of the table name.
CREATE TRIGGER car_trigger AFTER INSERT ON Car
FOR EACH ROW UPDATE Car SET NEW.CarID = NEW.InsuranceNumber
But you should know this won't work if you're trying to copy one auto-increment column to the other, because you can't change the values of NEW.* columns in an AFTER trigger. The row has already been inserted and it's too late to change values.
But in a BEFORE trigger, the auto-increment value has not yet been generated, and the auto-increment column will still be NULL.
The only way to make something equivalent to "two auto-increment columns" is to generate an auto value not using AUTO_INCREMENT but with some other mechanism, so you can supply the value to the row as you execute your SQL statement.
Related
I have a innodb table on mysql like this:
create table person (
id int not null auto_increment primary key,
name varchar(512),
birthdate date,
...
id_most_relevant int,
fulltext(name)
);
I'm want to create a trigger that, whenever a person is updated, the trigger will search other person with most relevant name (by using a full-text search) and put his id on the id_most_relevant field of the updated person, but only if this relevance is more than 95%. So, to get the percentage relevance, I devide the relevance of each person with the relevance of the new name from the person updated. Something like:
SELECT id FROM PERSON
INTO _id_most_relevant
WHERE
MATCH (name) AGAINST (_new_name) /
MATCH (new.name) AGAINST (_new_name) > 0.95
The variables _id_most_relevant and _new_name are previously declare on the trigger and the variable _id_most_relevant would be used to update the person table on id=NEW.id .
Anyone has an idea on how to do that trigger?
I'm using Mysql 5.6 and I can't update it, but I can create an auxiliary table if necessary.
CREATE TRIGGER tr_bu_person
BEFORE UPDATE
ON person
FOR EACH ROW
SET NEW.id_most_relevant = ( SELECT id
FROM person
WHERE id <> NEW.id
ORDER BY MATCH (name) AGAINST (new.name) DESC
LIMIT 1 );
But I'd avoid of FTS usage in the trigger - I'd prefer to set this column to NULL (or remove it at all) and update it to the most relevant row id value in row retrieving query (or, maybe, by event procedure).
I find out that is not possible to solve this problem using a trigger because whenever I update a person's name I will need the fulltext index already updated to get the second MATCH (on the denominator), but the fulltext index it only be updated after the tigger executes (even if it was a after update trigger).
So I have to solve this using other way, without triggers.
That said, I will close this post.
I have a table with (among others) two columns uid and parent_uid. I would like parent_uid to be equal to uid upon insertion.
uid is my primary key with AUTO_INCREMENT.
I have tried to set up a trigger as follow
CREATE TRIGGER set_parent_uid BEFORE INSERT ON seller
FOR EACH ROW SET NEW.parent_uid = NEW.uid;
The actual behaviour is not as expected. Indeed, I get 0 for parent_uid whereas I should get 1 and 2 respectively for 25diamonds.com and 24diamonds.com
uid,seller_url,website_url,name,country,discarded,parent_uid
1,25diamonds.com,25diamonds.com,25diamonds.com,NULL,0,0
2,24diamonds.com,24diamonds.com,24diamonds.com,NULL,0,0
It seems that NEW.uid is not the correct way to access it.
I have been having some frustration attempting to add data values to this table students. I have all the other data values and have dropped and created the column student_id. However, when trying to add the data with this query:
insert into students(student_id) values('1'),('2'),('3'),('4'),('5');
The data does not insert correctly, as it creates new columns below the first 5 which contain data.
It must be because of my not null values, but I can't not have the not null identifier.
Is there a query command that allows me to change data within already existing value-filled columns? I have been unsuccessful in finding this so far.
Here are some images to explain the problem further.
The query I have made to add my values to the table:
The data was inserted but as it is underneath the columns I need to map with a foreign key, I cannot use the column as the top 5 values are still my not null default, which is required to let me create the foreign key
Looks like you already have your records initially created without the student_id field, you want to UPDATE the current records but you're actually INSERTING new records.
You're meant to update your students with update statements such as "UPDATE students SET student_id = X where condition = Y"
Then it looks like your student_id is your primary key which you should set to AUTO_INCREMENT value.
Regards
INSERT is the wrong command since you want to update existing rows. The problem here lies within the fact that the order of the rows is nondeterministic and I think you cannot update them in one statement. One solution would be as follows:
UPDATE students SET student_id = 1 WHERE first_name = 'Berry';
UPDATE students SET student_id = 2 WHERE first_name = 'Darren';
I hope you really do have only 5 columns to update :-)
I have a two tables
MovieStar (
name: char(15),
address:varchar(40),
gender:char(1),
birthdate: date,
rating:float
)
StarsIn (
movieTitle:char(25),
movieYear:int,
starname:char(15),
role:varchar(15)
)
starName is foreign key which is related to name of MovieStar.
I want to increment rating by one when Starsin record is inserted and role of the new record is 'main'
What it would do is;
on insert to starsin, check whether role = 'main'
if so, what is starname
increment rating of moviestar name = starname
I would not store the value rating in your table as it can be derived from the other table's data when it is required. And why are you using float for the count?
Create a VIEW which counts the rows in Starsin, based on your condition role = 'main' and then you have no need for the trigger and the count will always be up to date when new rows are added or removed.
With the trigger solution you also have to take account of row deletion to decrement the count.
EDIT: From the comment you made, here's a sample trigger (although the syntax may be wrong as I mainly work with SQL Server). I'm assuming the name field in the MovieStar table is a primary key and therefore unique.
CREATE TRIGGER UpdateRating AFTER INSERT ON StarsIn
FOR EACH ROW
BEGIN
UPDATE MovieStar SET rating =
(SELECT rating FROM MovieStar WHERE name = NEW.starname) + 1
FROM MovieStar INNER JOIN NEW ON MoveStar.name = NEW.starname
WHERE NEW.role = 'main'
END
I'm not familiar with MySQL, I work with SQL Server, where triggers need to be set based. I'm guessing the FOR EACH ROW part of the trigger means the statements are executed for each row inserted, but I may be wrong about that.
You need to create a trigger on insert and do the intended update.
is there a way in SQL to create the constraint that a column has to be unique, if a specific column has a specific value?
Example: the rows are not really deleted, but marked as 'deleted' in the database. And within the 'not-deleted' rows, ValueA has to be unique:
ID ValueA ValueB Deleted
-----------------------------------------------------
1 'foo' 10 0
2 'bar' 20 0
3 'bar' 30 1
4 'bar' 40 1
5 'foo' 50 0 --NOT ALLOWED
I thought of something like a CHECK constraint, however I don't know how to do this.
with SQL92 this is not possible, may be you could implement something with a trigger
Can you change the design a little bit?
It seems to me that you have a list of "thingies". For each ValueA, there's a single active "thingy" at any one time. This can best be modeled as follows:
Remove ValueA and Deleted from your main Thingies table.
Create a new table ActiveThingies with columns ValueA and ID. Protect this table by making ValueA a unique or primary key. (You may also need to make ID unique as well depending on whether a single ID can represent more than 1 ValueA).
Now, use the ActiveThingies table to control which record is current at any time. To change the active (non-deleted) record for "foo", update it's ID column in ActiveThingies.
To get your list of non-deleted items join the two tables.
With this design, however, you will lose the ability to remember the ValueA for "deleted" "thingies". If you need to remember those values, you will also need to include the ValueA column in Thingies.
There is workaround this problem - create another column deleted_on
deleted_on timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
and make unique key on both ValueA and deleted_on
UNIQUE KEY not_deleted (ValueA, deleted_on)
When soft deleting a record insert NOW() for value of deleted_on
MySQL ignores CHECK constraints, so you cannot do this in MySQL as you might in another database.
Here is a hack. Unique constraint on valueA + deleted. When deleting rows you cannot use just 1, they must be 1, 2, 3...
This at least lets you do it server-side in MySQL, but introduces a step. When marking a row for deletion, you have to first go find the max(deleted), add 1, and plug that value in when marking for deletion.
Split your table into two tables: One which has a UNIQUE constraint on ValueA and one that doesn't. Use a view+triggers to combine the two tables. Something like:
CREATE TABLE _Active (
ID INTEGER,
ValueA VARCHAR(255) UNIQUE,
ValueB INTEGER
);
CREATE TABLE _Deleted (
ID INTEGER,
ValueA VARCHAR(255), /* NOT unique! */
ValueB INTEGER
);
CREATE VIEW Thingies AS
SELECT ID, ValueA, ValueB, 0 AS Deleted FROM _Active
UNION ALL
SELECT ID, ValueA, ValueB, 1 AS Deleted FROM _Deleted;
CREATE TRIGGER _trg_ii_Thingies_Active
INSTEAD OF INSERT ON Thingies
FOR EACH ROW WHEN NOT NEW.Deleted
BEGIN
INSERT INTO _Active(ID, ValueA, ValueB)
VALUES (NEW.ID, NEW.ValueA, NEW.ValueB);
END;
CREATE TRIGGER _trg_ii_Thingies_Deleted
INSTEAD OF INSERT ON Thingies
FOR EACH ROW WHEN NEW.Deleted
BEGIN
INSERT INTO _Deleted(ID, ValueA, ValueB)
VALUES (NEW.ID, NEW.ValueA, NEW.ValueB);
END;
/* Add triggers for DELETE and UPDATE as appropriate */
(I'm not sure about the CREATE TRIGGER syntax, but you know what I mean.)