I have a table defined in MySQL as following. Now I want to create this table in oracle.
But how can I convert on update trigger in to oracle?
create table test(
userid INTEGER(10) NOT NULL AUTO_INCREMENT,
CONSTRAINT PRIMARY KEY (userid),
fullname VARCHAR(200) NOT NULL,
email VARCHAR(50) NOT NULL,
createdat DATETIME NOT NULL DEFAULT NOW(),
updatedat DATETIME ON UPDATE NOW()
);
For a example, so:
CREATE TABLE test
(
userid INTEGER PRIMARY KEY
, fullname VARCHAR2(200) NOT NULL
, email VARCHAR2(50) NOT NULL
, createdat DATE DEFAULT CURRENT_DATE NOT NULL
, updatedat DATE
);
CREATE SEQUENCE test_seq START WITH 1 INCREMENT BY 1;
CREATE OR REPLACE TRIGGER test_insert
BEFORE INSERT
ON test
FOR EACH ROW
BEGIN
SELECT test_seq.NEXTVAL
INTO :new.userid
FROM DUAL;
END;
CREATE OR REPLACE TRIGGER test_update
BEFORE UPDATE
ON test
FOR EACH ROW
BEGIN
SELECT CURRENT_DATE
INTO :new.updatedat
FROM DUAL;
END;
Triggers may BEFORE UPDATE, AFTER UPDATE, and INSTEAD. Choose that you want. For more information read docs http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7004.htm
Since Oracle 12c, you can avoid using SEQUENCE in using IDENTITY as done in standard SQL.
The solution to your problem is following
CREATE TABLE test
( userid INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY
, fullname VARCHAR2(200) NOT NULL
, email VARCHAR2(50) NOT NULL
, createdat DATE DEFAULT CURRENT_DATE NOT NULL
, updatedat DATE
);
CREATE OR REPLACE TRIGGER test_update
BEFORE UPDATE
ON test
FOR EACH ROW
BEGIN
SELECT CURRENT_DATE
INTO :new.updatedat
FROM DUAL;
END;
Related
DROP TABLE IF EXISTS Sales;
CREATE TABLE Sales (
id INT AUTO_INCREMENT,
product VARCHAR(100) NOT NULL,
quantity INT NOT NULL DEFAULT 0,
fiscalYear SMALLINT NOT NULL,
fiscalMonth TINYINT NOT NULL,
CHECK(fiscalMonth >= 1 AND fiscalMonth <= 12),
CHECK(fiscalYear BETWEEN 2000 and 2050),
CHECK (quantity >=0),
UNIQUE(product, fiscalYear, fiscalMonth),
PRIMARY KEY(id)
);
DROP TABLE IF EXISTS log;
CREATE TABLE log (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
text VARCHAR(100)
);
Triggers
CREATE DEFINER=`root`#`localhost` TRIGGER `sales_AFTER_UPDATE` AFTER UPDATE ON `sales`
FOR EACH ROW
BEGIN
INSERT INTO log VALUES(NOW(),CONCAT('Update Student Record ', OLD.quantity));
END
UPDATE test for.sales SET quantity = 36
WHERE (id = 1);
ERROR 1136: 1136: Column count doesn't match value count at row 1
Iam new in mySQL Please help
You should specify columns in INSERT statement in your trigger explicitly, as you do not set all values in a row (auto incremented column excluded).
So it would be
INSERT INTO log(timestamp, text) VALUES (NOW(),CONCAT('Update Student Record ', OLD.quantity));
You have some errors.
First based on your trigger you need another column on log table which is as following
quantity INT NOT NULL DEFAULT 0
Second , do not use Keywords and Reserved Words like text and timestamp, it is a bad practice. If you do please put it inside backticks
Third your insert statement should be
INSERT INTO log(`timestamp`,`text`,quantity) VALUES(NOW(),'Update Student Record', OLD.quantity);
there is no need for CONCAT.
Fourth,
`sales`
table is not the same as Sales table, because you have used backticks.
Full working trigger below:
DELIMITER //
CREATE TRIGGER `sales_AFTER_UPDATE` AFTER UPDATE ON Sales
FOR EACH ROW
BEGIN
INSERT INTO log(`timestamp`,`text`,quantity) VALUES(NOW(),'Update Student Record', OLD.quantity);
END//
DELIMITER ;
Check working demo:
https://www.db-fiddle.com/f/iqwShcHK3AGJvU4MDbxDku/0
I am trying to calculate the differential column of the score table upon inserting into a MySQL 8.0 database using a before trigger. The calculation uses the coursetee table as well. The trigger works fine on all but the first record in the table, which doesn't get updated. Is there something that I am missing? All relevant code is below.
CREATE TABLE coursetee (
teeID INT UNSIGNED AUTO_INCREMENT,
tee_name VARCHAR(20) NOT NULL,
course_rating DECIMAL(3,1) NOT NULL,
slope_rating INT UNSIGNED NOT NULL,
par INT UNSIGNED,
CONSTRAINT pk_coursetee PRIMARY KEY (teeID),
CREATE TABLE score (
roundID INT UNSIGNED AUTO_INCREMENT,
teeID INT UNSIGNED,
round_score INT UNSIGNED NOT NULL,
round_date DATETIME NOT NULL,
entry_date DATETIME DEFAULT NOW() NOT NULL,
differential DECIMAL(3,1),
CONSTRAINT pk_score PRIMARY KEY (roundID),
CONSTRAINT fk_score_coursetee FOREIGN KEY (teeID) REFERENCES coursetee(teeID));
DELIMITER $$
CREATE TRIGGER calculate_differential
BEFORE INSERT ON score
FOR EACH ROW
BEGIN
SET NEW.differential = (SELECT ROUND((113/ct.slope_rating)*(NEW.round_score-ct.course_rating),1)
FROM score, coursetee as ct
WHERE NEW.teeID = ct.teeID AND differential IS NULL);
END$$
DELIMITER ;
INSERT INTO coursetee
(courseID,tee_name,course_rating,slope_rating,par)
VALUES
(1,'Back',74.7,143,72),
(1,'Middle',72.6,136,72),
(1,'Front',71.3,132,72),
(2,'Back',76.8,155,72),
(2,'Middle',73.9,146,72),
(2,'Front',65.3,125,72);
INSERT INTO score
(playerID,teeID,round_score,round_date)
VALUES
(1,2,79,'2019-07-25');
INSERT INTO score
(playerID,teeID,round_score,round_date)
VALUES
(2,2,80,'2019-07-25');
INSERT INTO score
(playerID,teeID,round_score,round_date)
VALUES
(1,2,77,'2019-08-06');
The query returns:
image of query not returning calculated record for row 1
CREATE TRIGGER calculate_differential
BEFORE INSERT
ON score
FOR EACH ROW
SET NEW.differential = ( SELECT ROUND((113/ct.slope_rating)*(NEW.round_score-ct.course_rating),1)
FROM coursetee ct
WHERE NEW.teeID = ct.teeID);
fiddle
The problem was in using score table as a source of the subquery. And the hope that differential BEFORE inserting the first record will give anything except NOT FOUND. And testing the field of the record BEFORE INSERT for NULL makes no sense.
My assumption is about the FROM clause of the differential query in the trigger. i'd suggest you to try change the order of the tables -
FROM score, coursetee as ct
to
FROM coursetee as ct, score
Seems like its trying to extract nothing for the first insert...
Hello this is my structure for tbl_patient:
CREATE TABLE tbl_patient
(
id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
idPatient varchar(15) DEFAULT NULL,
namePatient varchar(40) NOT NULL,
age int NOT NULL,
birthDate date,
gender varchar(15) NOT NULL,
status varchar(15) NOT NULL,
address varchar(255) NOT NULL,
work varchar(25) NOT NULL,
phone varchar(15) NOT NULL
)
ENGINE=InnoDb;
I want to put 2 triggers on tbl_patient:
CREATE TRIGGER patientTrigger
BEFORE INSERT ON tbl_patient
FOR EACH ROW
SET NEW.idPatient = CONCAT("PAS-",COALESCE((SELECT MAX(id)+1 from tbl_patient),1));
CREATE TRIGGER ageTrigger
BEFORE INSERT ON tbl_pasien
FOR EACH ROW
SET NEW.age = YEAR(CURDATE()) - YEAR(birthDate);
But I got some error with :
1235 - This version of MariaDB doesn't yet support 'multiple triggers with the same action time and event for one table'
How can I implement that 2 triggers on my table?
You could use computed columns instead:
CREATE TABLE tbl_patient
(
id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
idPatient varchar(15) AS (CONCAT("PAS-", id)),
namePatient varchar(40) NOT NULL,
age int AS (YEAR(CURDATE()) - YEAR(birthDate)),
birthDate date,
gender varchar(15) NOT NULL,
status varchar(15) NOT NULL,
address varchar(255) NOT NULL,
work varchar(25) NOT NULL,
phone varchar(15) NOT NULL
)
ENGINE=InnoDb;
Remarks:
1) Note that your code to calculate age is not correct, for example (2015-12-31 and 2016-01-01).
Better way to calcualte age:
SELECT YEAR(NOW()) - YEAR(birthDate) -
(DATE_FORMAT(birthDate, '%m%d') > DATE_FORMAT(NOW(), '%m%d')) AS age
2)
CREATE TRIGGER patientTrigger
BEFORE INSERT ON tbl_patient
FOR EACH ROW
SET NEW.idPatient = CONCAT("PAS-",COALESCE((SELECT MAX(id)+1 from tbl_patient),1));
is poor solution when multiple concurrent INSERTs occur.
EDIT
Using triggers you have update age when user update birthDate (yes it may happen).
Other possible solution is to simply create view.
CREATE VIEW vw_patient
AS
SELECT `id`, `namePatient`, `birthDate`,
`gender`, `status`, `address`, `work`, `phone`,
CONCAT("PAS-", id) AS `idPatient`,
YEAR(NOW()) - YEAR(birthDate) -
(DATE_FORMAT(birthDate, '%m%d') > DATE_FORMAT(NOW(), '%m%d')) AS `age`
FROM `tbl_patient`
SqlFiddleDemo
Try to merge body of both triggers into single one, something like this:
CREATE TRIGGER patientTrigger BEFORE INSERT ON tbl_patient FOR EACH ROW
BEGIN
SET NEW.idPatient = CONCAT("PAS-",COALESCE((SELECT MAX(id)+1 from tbl_patient),1));
SET NEW.age = YEAR(CURDATE()) - YEAR(birthDate);
END
I Want to add an Integer Column to a String that's because i need to generate a varchar variable with a numeric part that automatically increments. For example, P000001,P000002...
In order to do that what i am doing while creation of table i have taken an int field ID which auto_increments and i am Concatenating P with 00000 and the ID value
The Table i have created is :
CREATE TABLE tblAcceptTest(
ID int AUTO_INCREMENT NOT NULL primary key,
PatientID as CONCAT('P' , CONCAT('000000',CAST(ID as char)))
);
It Shows me the error from as keyword.
Please help
MySQL's documentation (http://dev.mysql.com/doc/refman/5.1/en/create-table.html) says, "the default value must be a constant; it cannot be a function or an expression." Why don't you just get the PatientID value afterward as part of the SELECT:
SELECT CONCAT('P', LPAD(ID, 6, 0)) AS PatientID FROM tblAcceptTest;
It looks like you want six digits after the "P", so try this for your expression:
CONCAT('P', LPAD(ID, 6, '0'))
Mysql has little support for computed columns.
Patient ID from your specification could be a char(7)
CREATE TABLE tblAcceptTest(
ID int AUTO_INCREMENT NOT NULL primary key,
PatientID char(7)
);
Then create some triggers. Note that the following insert trigger will cause issues with high concurrency servers.
DELIMITER |
CREATE TRIGGER tblAcceptTest_insert BEFORE INSERT ON tblAcceptTest
FOR EACH ROW BEGIN
DECLARE next_id INT;
SET next_id = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='tblAcceptTest');
SET NEW.PatientID = CONCAT('P' , RIGHT(CONCAT('000000',next_id),6)) ;
END;
|
CREATE TRIGGER tblAcceptTest_update BEFORE UPDATE ON tblAcceptTest
FOR EACH ROW BEGIN
SET NEW.PatientID = CONCAT('P' , RIGHT(CONCAT('000000',NEW.ID),6)) ;
END;
|
DELIMITER ;
You use relationships and views to achieve the same result.
CREATE TABLE `patient` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`patient` varchar(60) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `accepted_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`patient_id` int(11) NOT NULL,
`accepted` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `patient_id` (`patient_id`),
CONSTRAINT `accepted_test_ibfk_1` FOREIGN KEY (`patient_id`) REFERENCES `patient` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
create or replace view accepted_test_veiw as
select CONCAT('P' , RIGHT(CONCAT('000000',patient_id),6)) patient_key
, accepted
, id accepted_test_id
, patient_id
from accepted_test ;
select * from `accepted_test_veiw`
I'm trying to keep a list of current content and archived content in my PHP Internet application. I want to be able to identify the content that as archived as having an enddate, and the content that is not archived as having no enddate. It would be ideal if I could create more paths, but I'm hoping to just start here.
The first thing I'm noticing is that I'm getting a syntax error at the " on line 1, but there is no double quote where I create the table. The second issue I'm having is the use of TIMESTAMP as a datatype. I tried to use CURRENT_TIMESTAMP for the startdate, and it returned syntax errors. The final problem I am having is with the trigger construction. I'm not able to get down far enough to troubleshoot it. As soon as I get past the references, I'll also try to troubleshoot that.
CREATE TABLE plan(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32),
startdate TIMESTAMP NOT NULL,
enddate TIMESTAMP);
CREATE TABLE level(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32),
description VARCHAR(500),
startdate TIMESTAMP NOT NULL,
enddate TIMESTAMP);
CREATE TABLE planIDxlevelID(
planID INT NOT NULL REFERENCES plan(id),
levelID INT NOT NULL REFERENCES level(id),
arXORcur ENUM('archive', 'current');
);
delimiter |
CREATE TRIGGER testref BEFORE INSERT ON plan
FOR EACH ROW BEGIN
INSERT INTO plan(id, plan, startdate, enddate)
SET id = LAST_INSERT_ID( id + 1), name = NEW.name, startdate = NEW.UTC_TIMESTAMP, enddate = NULL;
UPDATE plan(enddate) WHERE plan.id = OLD.id
SET enddate = UTC_TIMESTAMP;
INSERT INTO planIDxlevelID(planID, levelID, arXORcur)
SET planID = NEW.planID, levelID = OLD.levelID, arXORcur = current;
UPDATE planIDxlevelID(planID, levelID, arXORcur) WHERE planID = OLD.planID
SET planID = OLD.planID, levelID = OLD.levelID, arXORcur = archive;
END;
|
delimiter ;
INSERT INTO plan (name) VALUES
"Frogs", "Toys", "Trucks", "Nature", "Seasons",
"Construction", "Candy", "Rainbows", "Telephone", "Breakfasts";
TIMESTAMP vs DATETIME
This is a classic gotcha: TIMESTAMP is a special datatype that
is updated with "now" every time the row is touched, whether you update it to another value or leave it alone. What you want is DATETIME.
Next, you have numerous syntax and other errors. The following executes without error, however it may not now have the logic you want, but you can edit it to fix that:
CREATE TABLE plan (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32),
startdate DATETIME NOT NULL, -- changed TIMESTAMP to DATETIME
enddate DATETIME -- changed TIMESTAMP to DATETIME
);
CREATE TABLE level (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32),
description VARCHAR(500),
startdate DATETIME NOT NULL, -- changed TIMESTAMP to DATETIME
enddate DATETIME -- changed TIMESTAMP to DATETIME
);
CREATE TABLE planIDxlevelID (
planID INT NOT NULL REFERENCES plan(id),
levelID INT NOT NULL REFERENCES level(id),
arXORcur ENUM('archive', 'current')
);
DROP TRIGGER IF EXISTS test_insert;
delimiter |
CREATE TRIGGER test_insert BEFORE INSERT ON plan
FOR EACH ROW BEGIN
INSERT INTO plan (id, plan, startdate)
values (LAST_INSERT_ID() + 1, NEW.name, NEW.UTC_TIMESTAMP());
INSERT INTO planIDxlevelID (planID, levelID, arXORcur)
values (NEW.ID, null, arXORcur = current);
END;|
delimiter ;
DROP TRIGGER IF EXISTS test_update;
delimiter |
CREATE TRIGGER test_update BEFORE UPDATE ON plan
FOR EACH ROW BEGIN
UPDATE plan SET
enddate = UTC_TIMESTAMP
WHERE plan.id = OLD.id;
UPDATE planIDxlevelID SET
planID = NEW.ID,
levelID = null,
arXORcur = archive
WHERE planID = OLD.ID;
END;|
delimiter ;
INSERT INTO plan (name) VALUES
("Frogs"), ("Toys"), ("Trucks"), ("Nature"), ("Seasons"),
("Construction"), ("Candy"), ("Rainbows"), ("Telephone"), ("Breakfasts");