mysql procedure for insert with select from another table - mysql

I want to create a procedure that creates a course for a user this takes one parameter that is userid and the other value will be selected from tbl_chapter.there are 27 chapters that are going to be selected and 27 inserts will be executed .insert is going to be like INSERT INTO tbl_user_chapter(user_id,chapter_id) VALUEs (9 , 1),(9,2),(9,3),....
I want something like this:
CREATE PROCEDURE createCourse (IN userid_param int)
BEGIN
INSERT INTO tbl_user_chapter(tbl_user_chapter.user_id,tbl_user_chapter.chapter_id) VALUE(userid_param , SELECT id FROM tbl_chapter)
END
SELECT id FROM tbl_chapter will be multiple rows.
I know this is wrong and I need help.
if there is a better way to do this please let me know.

If the select does not return one row, then don't use the VALUES( ) syntax. Use INSERT ... SELECT syntax:
CREATE PROCEDURE createCourse (IN userid int)
BEGIN
INSERT INTO tbl_user_chapter(user_id,chapter_id)
SELECT userid, id FROM tbl_chapter;
END
Make sure userid does NOT conflict with a column of the same name in your tbl_chapter table. If a column exists with that name, you should change the IN parameter of the stored procedure.

Related

MySQL set column value to upper case value of another column

I have a requirement where in my sql a column 2 would always have the uppercase value that is column 1,
Not sure ow to do this in mysql. I want to do something like this , I know the syntax below is incorrect but writing some psuedo code as to make it clear what I am trying to achieve
create table sakila.testupper(name varchar(50),
uppername varchar(50) not null default as select upper(#name));
I believe you could accomplish this across most version of MySQL with a trigger on insert or update: http://dev.mysql.com/doc/refman/5.7/en/triggers.html
The syntax you're after looks like this: "create table sakila.testupper (name varchar(50), uppername varchar(50) generated always as (upper(name)));". However, you'd need a recent release of MySQL version 5.7.
You can't have the table do this automatically but you can create a trigger for all future INSERTs. With a trigger you will need to maintain a separate table.
drop table if exists p;
drop table if exists q;
create table q (name nvarchar(59),uppername nvarchar(59));
create table p (name nvarchar(59));
create trigger trig_thing after insert on p
for each row
begin
insert into q set name = new.name, uppername = upper(new.name);
end;
insert into p (name) values ('Some nice gentleman');
insert into p (name) values ('A sweet old lady');
select * from q;
Your original table will keep only the name, but each insert will cause a trigger to insert the same data into your new table with name and uppername.
If you already have names stored in a table you should insert into your second table to get them in line before you set up the trigger:
insert into q name, upper(name) from p;
here is a functional example

Merge stored procedure with datatype conversions

I am able to execute my stored procedure. When I execute it a second time instead of updating the existing values same values from source are inserted as new values.
i.e my target has
1
2
3
When I run the stored procedure a second time, instead of updating 1,2,3, it is inserting the same
1
2
3
1
2
3
My condition for when matched then select S.REPORT_TEST1 except T.REPORT_TEST1 is not working.
When I use the same code on a different table which doesn't have data conversions I am able to update.
Can anyone tell where am I going wrong?
CREATE PROCEDURE [dbo].[Merge]
INSERT INTO .[dbo].[TARGET](REPORT_TEST1, REPORT_TEST2, REPOST_TEST3)
FROM (MERGE [dbo].[TARGET] T
USING (SELECT
Cast([REPORT TEST1] as int) [REPORT_TEST1],
Cast([REPORT TEST2] as int) [REPORT_TEST2],
Cast([REPORT TEST3] as int) [REPORT_TEST3]
FROM
[dbo].[SOURCE]) S ON (T.[REPORT_TEST1] = S.[REPORT_TEST1])
WHEN NOT MATCHED BY TARGET
THEN INSERT
VALUES (S.REPORT_TEST1, S.REPORT_TEST2, S.REPOST_TEST3)
WHEN MATCHED
AND EXISTS (SELECT S.REPORT_TEST1, S.REPORT_TEST2, S.REPOST_TEST3
EXCEPT
SELECT T.REPORT_TEST1, T.REPORT_TEST2, T.REPOST_TEST3)
OUTPUT $ACTION ACTION_OUT,
S.REPORT_TEST1, S.REPORT_TEST2, S.REPOST_TEST3) ;
Thanks
would it not suffice to rewrite your WHEN MATCHED statement thusly:
WHEN MATCHED
AND S.REPORT_TEST2 <> T.REPORT_TEST2
AND S.REPORT_TEST3 <> T.REPORT_TEST3
(
SELECT
S.REPORT_TEST1
,S.REPORT_TEST2
,S.REPOST_TEST3
)
I think I understand what you're trying to do, but inside the MERGE context, you're only comparing this row with that row, not the source row against the whole target table. you could modify the subselect thusly if you're trying to query "this source is not at all in the target"
WHEN MATCHED AND EXISTS
(
SELECT
S.REPORT_TEST1
,S.REPORT_TEST2
,S.REPOST_TEST3
EXCEPT SELECT
T2.REPORT_TEST1
,T2.REPORT_TEST2
,T2.REPOST_TEST3
FROM
[dbo].[TARGET] T2
)

Mysql Insert if not exist in two column

I looked into MySQL duplicate key but cant figure it out.
I have a table like below:
id series chapter path(can be unique)
I want only insert data and not update. Lets say I have data like below:
seri:Naruto, klasor:567 ==> If both of these exist in table then do not insert.
seri:Naruto, klasor:568 ==> If Naruto exist but 568 does not exist then do insert.
How can I achieve this?
Easiest way would be to define unique index with two columns on that table:
ALTER TABLE yourtable ADD UNIQUE INDEX (seri,klasor);
You may also define two column primary key, which would work just as well.
Then use INSERT IGNORE to only add rows when they will not be duplicates:
INSERT IGNORE INTO yourtable (seri, klasor) VALUES ('Naruto',567);
INSERT IGNORE INTO yourtable (seri, klasor) VALUES ('Naruto',568);
Edit: As per comments, you can't use UNIQUE INDEX which complicates things.
SET #seri='Naruto';
SET #klasor=567;
INSERT INTO yourtable
SELECT seri,klasor FROM (SELECT #seri AS seri, #klasor AS klasor)
WHERE NOT EXISTS (SELECT seri, klasor FROM yourtable WHERE seri=#seri AND klasor=#klasor);
You may use the above query with two local variables or convert it to single statement by replacing the local variables with actual values.
Better way would be to use stored procedure:
CREATE PROCEDURE yourinsert (vseri VARCHAR(8), vklasor INT)
BEGIN
DECLARE i INT;
SELECT COUNT(*) INTO i FROM yourtable WHERE seri=vseri AND klasor=vklasor;
IF i=0 THEN
INSERT INTO yourtable (seri,klasor) VALUES (vseri, vklasor);
END IF;
END;
This would allow you to perform the INSERT using:
CALL yourinsert('Naruto',567);
INSERT INTO table_name (seri, klasor) VALUES ('Naruto',567)
WHERE NOT EXISTS( SELECT seri,klasor FROM table_name WEHERE seri='Naruto' AND klasor=567
)
Hope this helps..

Add a row if there are less than 5, otherwise replace the lowest number in MySQL

I'm pretty stuck on a Mysql query.
I have a table with three columns;
user_id | person_id | score.
The table is going to be used to store top 5 highscores for each person.
I need at query that checks if there is less than five rows for a specific person.
Is there is less, insert new row. But if there is five rows I have to replace the lowest score with the new one.
It is for a webservice written in PHP and the data about the new score is posted to the method as params.
Been stuck for some hours now — is it even possible to make this happen in one query ?
You can use stored procedure in mysql. I dont know the names of the tables but if you look closer you will understand how it works.
DELIMITER $$
DROP PROCEDURE IF EXISTS test $$
CREATE PROCEDURE test( IN testparam VARCHAR(22) )
BEGIN
DECLARE count INT(11);
SET count = (SELECT COUNT(*) FROM persons );
IF count < 5 THEN
insert into table_needed_for_insert values(testparam);
ELSE
update table_needed_for_insert where score=(select min(score) from table_needed_for_insert);
END IF;
select * from table_needed_for_insert
END $$
DELIMITER;
And how to execute this thing CALL test(1); 1 is the parameter, you can create as many as you need.
And from php you can call directly as like
$result = mysql_query("call test(".$param.")");
And here you can check a tutorial on mysql stored procedures:
http://www.mysqltutorial.org/mysql-stored-procedure-tutorial.aspx
It might be possible if you have a unique key which identifies the lowest score. Then you could use the
INSERT ... ON DUPLICATE KEY construct. But you would have to install a trigger which keeps explicit track of the lowest score.
I would propose this scenario (I have not tried it, it is just an idea):
as I understand, you only need 5 ids. you can run a subqueries like these
SELECT MAX(id) AS last_id FROM table
SELECT MIN(score), id AS lowest_id FROM table
then
insert or replace into table (id, ...) values ( MIN(last_id+1, lowest_id), ... )
there are possible mistakes and also only one subquery is possible, but I hope you get the main idea
The simplest way imo is to insert data,
INSERT INTO top_scores (user_id, person_id, score_id) VALUES (1,2,3)
then delete inappropriate rows
DELETE top_scores FROM top_scores
INNER JOIN
(SELECT * FROM top_scores WHERE person_id = 2 ORDER BY score ASC LIMIT 5, 1000000) AS inappropriate_rows
USING (user_id, person_id, score)

Mysql: Insert Procedure with two tables (FK)

Im trying to make an stored Procedure that makes an insert into tables.
The insert effects two tables and there is an FK between them.
CREATE PROCEDURE `db`.`add_user_hr` (
IN in_Pass VARCHAR(45),
IN in_Value VARCHAR(45),
IN in_HR_ID INT,
)
BEGIN
INSERT INTO HR
(
Value
)
VALUES
(
in_Value
);
INSERT INTO User
(
Password,
HR_idHR
)
VALUES
(
in_Pass,
(Get the ID from HR)
);
END
How do I make sure that the correct id gets into User. And
if there is a error in the insert into HR, who do I make
sure it dosent tyr to make an insert into User? Ive
looked into "commit" but don't know how it's used.
Or is there a better way to do this?
In this example I have table UserType. Is this needed to
to find out witch type of user it is later on? And
how do I user this in the insert, select procedure in the
future?
Thx for all the help!
If PK (primary key) has AUTO_INCREMENT options than you can do something like this:
declare value_id_v INT;
insert into hr(value) values(value_in);
set value_id_v = last_insert_id();
Now you can use value_id_v to do inserts. Here is the link to read about this function LAST_INSERT_ID