delimeter //
DROP function IF EXISTS get_seq_next//
create function get_seq_next(
IN sequence_ref_ varchar(30)
) returns int(11) unsigned
BEGIN
DECLARE seq_val_ int(11) unsigned;
LOCK TABLE ga_seq_tab WRITE;
select sequence_no into seq_val_ from ga_seq_tab where sequence_ref=sequence_ref_;
if not seq_val_ is null then
update ga_seq_tab set sequence_no=sequence_no+1 where sequence_ref=sequence_ref_;
end if
UNLOCK TABLES;
return seq_val;
END //
DELIMETER ;
I'm trying to create a function but it keeps saying I have syntax errors and I am not sure what is wrong with it
Try removing the IN reserved word in the parameters list.
Related
I keep getting a syntax error at line 9
CREATE PROCEDURE `ItemsAddOrEdit`(
_itm_id INT,
_itm_name VARCHAR(255),
_itm_price FLOAT(8,2)
)
BEGIN
IF _itm_id = 0 THEN
INSERT INTO items (itm_name, itm_price)
VALUES (_itm_name, _itm_price);
ELSE
UPDATE items
SET
itm_name = _itm_name,
itm_price = _itm_price
WHERE itm_id = _itm_id;
END IF;
END
Are the variables the problem? I've checked the table to see if I messed the names up, but it all seems fine to me.
Here's the table code
CREATE TABLE `items` (
`itm_id` INT(255) NOT NULL AUTO_INCREMENT,
`itm_name` VARCHAR(255) NOT NULL,
`itm_price` FLOAT(8,2) NOT NULL,
PRIMARY KEY (`itm_id`),
UNIQUE INDEX `itm_name` (`itm_name`)
)
You need to redefine Delimiter to something else, for eg: $$. This allows parser to ignore ; (hence do not execute statement on reaching ;).
Also, as a good practice, always use DROP PROCEDURE IF EXISTS, to avoid failing out in case procedure with same name already exists.
At the end, redefine the Delimiter back to ;
Try the following:
DELIMITER $$
DROP PROCEDURE IF EXISTS `ItemsAddOrEdit` $$
CREATE PROCEDURE `ItemsAddOrEdit`(
_itm_id INT,
_itm_name VARCHAR(255),
_itm_price FLOAT(8,2)
)
BEGIN
IF _itm_id = 0 THEN
INSERT INTO items (itm_name, itm_price)
VALUES (_itm_name, _itm_price);
ELSE
UPDATE items
SET
itm_name = _itm_name,
itm_price = _itm_price
WHERE itm_id = _itm_id;
END IF;
END $$
DELIMITER ;
I'm working with a db where the keys are all binary(16), essentially stored as a GUID with a couple of the values flipped around. I have a simple stored procedure where I want to filter out a single by ID.
delimiter //
create procedure select_item_by_id (
in id binary(16)
)
begin
select
`id`,
`name`
from
`item`
where
`id` = id;
end //
delimiter ;
When I fire it like so, it pulls back all the records in the table, no filtering is done:
call select_item_by_id(unhex('11e7deb1b1628696ad3894b2c0ab197a'));
However, if I run it manually...it filters the record exactly as expected:
select
`id`,
`name`
from
`item`
where
`id` = unhex('11e7deb1b1628696ad3894b2c0ab197a');
I even tried passing in a string/chars and doing the unhex inside of the sproc, but that pulls zero results:
delimiter //
create procedure select_item_by_id (
in id char(32)
)
begin
select
`id`,
`name`
from
`item`
where
`id` = unhex(id);
end //
delimiter ;
call select_item_by_id('11e7deb1b1628696ad3894b2c0ab197a');
Pretty weird. What am I doing wrong?
It's likely that WHERE id = id is always evaluating to true, as it might be checking if the row's id is equal to itself. Rename the parameter to something else.
Rename the parameter of your proc:
create procedure select_item_by_id (
in idToTest char(32)
)
and use
where
`id` = idToTest;
to avoid ambiguity.
I want to update two tables at the same time in my database. One table is for groups, and the other table is for members of groups:
CREATE TABLE IF NOT EXISTS groups (
group_id INTEGER UNSIGNED AUTO_INCREMENT,
group_name VARCHAR(150) NOT NULL DEFAULT '',
group_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (group_id)
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8;
CREATE TABLE IF NOT EXISTS group_members (
group_mem_user_id INTEGER UNSIGNED NOT NULL,
group_mem_group_id INTEGER UNSIGNED NOT NULL,
group_mem_role TINYINT DEFAULT 1,
group_mem_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT group_mem_pk PRIMARY KEY (group_mem_user_id, group_mem_group_id),
FOREIGN KEY (group_mem_user_id) REFERENCES user (user_id),
FOREIGN KEY (group_mem_group_id) REFERENCES groups (group_id)
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8;
I want to use a stored procedure to create an entry in group and create an entry in group_members with the id that was just created for the group.
I know how to do this on the server (I have a java server and I'm using Spring's JdbcTemplate to make calls to the database) but I thought it would be better and more efficient to do this in a stored procedure.
The two individual queries are (im using prepared statements):
INSERT INTO groups (group_name) VALUES (?)
and
INSERT INTO group_members (group_mem_user_id, group_mem_group_id, group_mem_role) VALUES (?,?,?)
But I'm not sure how to merge these into one stored procedure.
DELIMITER //
DROP PROCEDURE IF EXISTS create_group //
CREATE PROCEDURE create_group(
#in/out here
)
BEGIN
#no idea
END //
DELIMITER ;
Ideally I would like it to return some value describing whether the operation was sucessful or not.
I use the following procedure:
DELIMITER //
DROP PROCEDURE IF EXISTS create_group //
CREATE PROCEDURE create_group(
IN create_group_group_name VARCHAR(150),
IN create_group_user_id INT
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
BEGIN
ROLLBACK;
END;
START TRANSACTION;
INSERT INTO groups (group_name) VALUES (create_group_group_name);
INSERT INTO group_members (group_mem_user_id, group_mem_group_id, group_mem_role) VALUES (create_group_user_id, LAST_INSERT_ID(), 2);
COMMIT;
END //
DELIMITER ;
In my server I use it like:
JdbcTemplate jt = new JdbcTemplate(DB.getDataSource(DB_USER));
int i = jt.update("CALL create_group (?,?)", new Object[] {groupName, userId});
if (i != 1)
throw new SQLException("Error creating group with name=" + groupName + " for userid=" + userId);
i == 1 if everything went well. Groups will never be created if the user is not added as a member (fixing the problem with my first iteration below).
OLD
(non-transactional, causes a problem if the second insert fails then the group is created with no members, it might work in some cases which is why I leave it here but it doesn't work for me)
The following procedure works. It does not return anything and I am just using the fact that the procedure completes without error to assume that it was all ok.
DELIMITER //
DROP PROCEDURE IF EXISTS create_group //
CREATE PROCEDURE create_group(
IN create_group_group_name VARCHAR(150),
IN create_group_user_id INT
)
BEGIN
INSERT INTO groups (group_name) VALUES (create_group_group_name);
INSERT INTO group_members (group_mem_user_id, group_mem_group_id, group_mem_role) VALUES (create_group_user_id, LAST_INSERT_ID(), 2);
END //
DELIMITER ;
Getting the warning 0 row(s) affected, 1 warning(s):
1072 Key column 'name' doesn't exist in table And I do not know what it means. Does anybody have an explaination?
The table/SP is as follows
CREATE TABLE IF NOT EXISTS `sectors`
(
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT ,
`sector` VARCHAR(25) NOT NULL ,
--
PRIMARY KEY (`id`) ,
UNIQUE INDEX `sector_idx` USING BTREE (`sector` ASC)
);
DELIMITER $$
CREATE PROCEDURE `AddSector` (IN sector VARCHAR(25),
OUT result BOOLEAN)
MODIFIES SQL DATA
BEGIN
DECLARE CONTINUE HANDLER FOR SQLWARNING, SQLEXCEPTION SET result = FALSE;
SET result = TRUE;
--
INSERT INTO `sectors` (`sector`) VALUES (sector);
COMMIT;
END $$
Change the procedure to:
DELIMITER $$
CREATE PROCEDURE `AddSector` (IN pSector VARCHAR(25), <<-- fix nameclash here
OUT result BOOLEAN)
MODIFIES SQL DATA
BEGIN
DECLARE CONTINUE HANDLER FOR SQLWARNING, SQLEXCEPTION SET result = FALSE;
SET result = TRUE;
INSERT INTO `sectors` (`sector`) VALUES (pSector); <<-- and here
-- COMMIT; <<-- You don't need a commit.
END $$
All stuff inside a stored proc is already run inside an implicit transaction, so the commit is not needed, and may actually be an error (not sure).
DELIMITER ;
I'm tumbled with a problem!
I've set up my first check constraint using MySQL, but unfortunately I'm having a problem. When inserting a row that should fail the test, the row is inserted anyway.
The structure:
CREATE TABLE user (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
uname VARCHAR(10) NOT NULL,
fname VARCHAR(50) NOT NULL,
lname VARCHAR(50) NOT NULL,
mail VARCHAR(50) NOT NULL,
PRIMARY KEY (id),
CHECK (LENGTH(fname) > 30)
);
The insert statement:
INSERT INTO user VALUES (null, 'user', 'Fname', 'Lname', 'mail#me.now');
The length of the string in the fname column should be too short, but it's inserted anyway.
I'm pretty sure I'm missing something basic here.
MySQL doesn't enforce CHECK constraints, on any engine.
Which leads me to ask, why would you declare the fname column as VARCHAR(50), but want to enforce that it can only be 30 characters long?
That said, the only alternative is to use a trigger:
CREATE TRIGGER t1 BEFORE INSERT ON user
FOR EACH ROW BEGIN
DECLARE numLength INT;
SET numLength = (SELECT LENGTH(NEW.fname));
IF (numLength > 30) THEN
SET NEW.col = 1/0;
END IF;
END;
As mentioned above you have to use a trigger, MySQL doesn't support check, also when you have multiple statements inside your trigger block, like declaring variables or control flows, you need to start it with begin and end and enclose your trigger inside two delimiters:
Note: If you use MariaDB use // after the first delimiter and before the second delimiter, otherwise if you use MySQL use $$ instead.
delimiter //
create trigger `user_insert_trigger` before insert on `user` for each row
begin
declare maximumFnameLength int unsigned;
declare fNameLength int unsigned;
set maximumFnameLength = 30;
set fNameLength = (select length(new.fNameLength));
if (fNameLength > maximumFnameLength) then
signal sqlstate '45000'
set message_text = 'First name is more than 30 characters long.';
end if;
end
//
delimiter ;