I'am trying to create a procedure checking table and insert
but it show me some error which i'am not sure how to fix it
this is the error code
Explicit or implicit commit is not allowed in stored function or
trigger
DELIMITER ;;
CREATE FUNCTION `getLabel`(paradocid INT, paradoctype char(10),paradoclineid INT,paraqty INT,paracreated date,paracreatedby INT) RETURNS int(100)
BEGIN
DECLARE transtotal int;
DECLARE i int DEFAULT 0;
DECLARE total int;
CREATE TABLE IF NOT EXISTS `sim_lable`(
`label_id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`doctype` varchar(10) NOT NULL,
`docid` int NOT NULL,
`doclineid` int NOT NULL,
`created` date NOT NULL,
`createdby` int NOT NULL
) ENGINE='InnoDB' COLLATE 'utf8_unicode_ci';
DELETE FROM sim_lable where
(TIME_TO_SEC(TIMEDIFF(paracreatedby,createdby))/60) >30;
SELECT #total=coalesce(count(*),0) as total2 from sim_label where
doctype=paradoctype and paradocid=docid;
IF total = 0 THEN
WHILE i < paraqty DO
INSERT INTO dbo.Students
(
`doctype` ,
`docid`,
`doclineid` ,
`created` ,
`createdby`
)
VALUES
(
paradoctype,
paradocid,
paradoclineid,
paracreated,
paracreatedby
) ;
END WHILE;
END IF;
END
As the error message says, explicit or implicit commit is not allowed in stored function or trigger. CREATE TABLE statement causes an implicit commit, therefore it is not allowed in a function.
Your code does not seem to return any value (there is no return statement in the function's body) and what you are doing there should be done in a stored procedure, rather than in a function.
Related
I am trying to populate a mqsql table with random values. I created a stored procedure for this but it gives me the error "column count doesn't match with the value count in row 1" when I execute it.
Below is what I have tried
The stored procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `GenerateManagerData`()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 100 DO
INSERT INTO projectManager(id,name,email,contact_number) VALUES (i+ 'M', CAST(i AS CHAR(10)), 'e'+ CAST(i AS CHAR(10))+ '#gmail.com', 'TP' + CAST(i AS CHAR(10)));
SET i = i + 1;
END WHILE;
END
This is the table I have created
CREATE TABLE `projectmanager` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`contact_number` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email_UNIQUE` (`email`)
);
I have given all the columns in the stored procedure. Please help me with this.
It was an issue with the CAST funation. Using CONCAT() fixed the issue,
CREATE DEFINER=`root`#`localhost` PROCEDURE `GenerateManagerData`()
BEGIN
DECLARE i INT DEFAULT 38;
WHILE i <= 100 DO
INSERT INTO projectManager(name,email,contact_number) VALUES (CONCAT('M', i), CONCAT('e', i, '#gmail.com'), CONCAT('TP', i));
SET i = i + 1;
END WHILE;
END
I have a problem with a Stored Procedure in MySQL. I want to get a single row by passing the ID parameter, however, it seems the SP ignores the WHERE filter and displays all the columns of the table.
What I find strange is that if I pass a specific value for id in a query outside the stored procedure, for example 1003, returns the expected result.
Sorry if my mistake is silly, I'm newbie.
The table structure is something like this:
CREATE TABLE Paciente
(
ID INT AUTO_INCREMENT NOT NULL,
DNI CHAR(8) UNIQUE NULL,
Nombre NVARCHAR(70) NOT NULL,
Apellido_Paterno NVARCHAR(30) NOT NULL,
Apellido_Materno NVARCHAR(30) NOT NULL,
Edad TINYINT NOT NULL,
Sexo CHAR(1) NOT NULL,
Calle NVARCHAR(50) NULL,
Numero_Domicilio SMALLINT(4) NULL,
Telefono NVARCHAR(8) NULL,
Movil NVARCHAR(10) NULL,
Estado_Civil NVARCHAR(20) NULL,
Ocupacion NVARCHAR(30) NULL,
Fecha_Registro DATETIME DEFAULT CURRENT_TIMESTAMP,
Estado BOOLEAN NULL DEFAULT TRUE,
PRIMARY KEY(ID)
)ENGINE = InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1000;
Stored Procedure:
DELIMITER $$
CREATE PROCEDURE `buscarPaciente`(IN id INT)
BEGIN
SELECT * FROM Paciente WHERE ID = id LIMIT 1;
END
$$
DELIMITER ;
The behaviour is caused by naming the input parameter same as the column name, therefore mysql cannot distinguish between the column and the parameter within the where clause. Rename the input parameter to let's say param_ID and it will return the record with the requested ID value.
DELIMITER $$
CREATE PROCEDURE `buscarPaciente`(IN param_ID INT)
BEGIN
SELECT * FROM Paciente WHERE ID = param_ID LIMIT 1;
END
$$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE `Student`(IN param_ID INT)
BEGIN
SELECT * FROM Student WHERE **Student.ID = param_ID** LIMIT 1;
END
$$
DELIMITER ;
I'm working on an Android program that introduces in a table approximately 15000 integer values(somewhere between 350-500 lines with 32 columns). In the DB I also have other similar values. This 15000 values that I'm talking about represent a processed image, so basically I want to compare the similarity of two images. Now, when I try to compare the values of two images(I'm comparing value by value and count the equal ones), only the data writing process takes about 7 minutes, which is way too long(I want to be able to write and compare at least 5 images in that time). I know that usually you don't work with this kind of things directly in the DB, but do you think that there is anything that I can do, or is it necessary to do this comparison on the server? The values returned by the descriptor came as line elements separated by ',' and each line is separated by ';'. I take each returned element and save it in a tables column. Here is my code:
Split function:
CREATE DEFINER=`root`#`localhost` FUNCTION `strSplit`(textIn longtext, delim varchar(12), count int) RETURNS int(11)
BEGIN
declare splitString INT(11);
SET splitString = replace(substring(substring_index(textIn, delim, count), length(substring_index(textIn, delim, count - 1)) + 1), delim, '');
RETURN splitString;
END
The function that creates the table:
CREATE TABLE IF NOT EXISTS `myguide`.`objectlocation` (
`ObjectLocationId` INT(11) NOT NULL AUTO_INCREMENT,
`ValueObject` LONGTEXT NOT NULL,
`DescriptorSize` INT(11) NOT NULL,
`DescriptionObject` VARCHAR(45) NOT NULL,
`DataInsert` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`InsertBy` VARCHAR(45) NULL DEFAULT NULL,
PRIMARY KEY (`ObjectLocationId`))
ENGINE = InnoDB
AUTO_INCREMENT = 2
DEFAULT CHARACTER SET = utf8
And this is the code that does the insert part:
CREATE DEFINER=`root`#`localhost` PROCEDURE `myguide_sp_info_imageId`(descriptorIn longtext, sizeDescriptor INT)
BEGIN
declare sizeImagesTable INT DEFAULT (select count(*) from objectLocation);
declare descriptorSizeImage INT;
declare descriptor INT;
declare sizeDescriptorImage INT DEFAULT sizeDescriptor;
declare contorInsertImage INT default 1;
declare descriptorForSplit longtext;
declare descriptorImageSaved longtext;
declare descriptorForSplitImageSaved longtext;
/* check if table exist, drop*/
DROP TEMPORARY TABLE IF EXISTS backupObjectLocation;
/* Create temporar table for store info about objectLocation*/
CREATE TEMPORARY TABLE backupObjectLocation (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
idImage int NOT NULL,
descriptorSaved longtext not null,
sizeDescriptorSaved float not null
);
/* check if table exist, drop*/
DROP TEMPORARY TABLE IF EXISTS processImage;
/* Create temporar table for store info about objectLocation*/
CREATE TEMPORARY TABLE processImage (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
descriptorSaved varchar(255) ,
descriptorReceived varchar(255)
);
SET descriptorImageSaved = RTRIM(descriptorIn);
SET descriptorForSplit = REPLACE(descriptorImageSaved, ';', ',');
INSERT INTO backupObjectLocation (idImage, descriptorSaved, sizeDescriptorSaved)
SELECT ObjectLocationId, ValueObject, DescriptorSize FROM objectLocation;
loop_insertDescriptorImage: LOOP
if contorInsertImage > sizeDescriptorImage then
leave loop_insertDescriptorImage;
end if;
SET descriptor = strSplit(descriptorForSplit, ',', contorInsertImage);
INSERT INTO processImage (descriptorReceived) VALUES (descriptor);
SET contorInsertImage = contorInsertImage + 1;
ITERATE loop_insertDescriptorImage;
end LOOP;
loop_table: LOOP
if sizeImagesTable > 1 then
leave loop_table;
end if;
SET descriptorSizeImage = (SELECT sizeDescriptorSaved from backupObjectLocation where id = sizeImagesTable);
loop_image: LOOP
if descriptorSizeImage > 1 then
leave loop_image;
end if;
SET descriptorImageSaved = (SELECT descriptorSaved from backupObjectLocation where id = sizeImagesTable);
SET descriptorForSplitImageSaved = REPLACE(descriptorImageSaved, ';', ',');
SET descriptorSizeImage = descriptorSizeImage + 1;
ITERATE loop_image;
end LOOP;
SET sizeImagesTable = sizeImagesTable + 1;
ITERATE loop_table;
end LOOP;
select descriptorImageSaved;
select * from backupObjectLocation;
select * from processImage;
END
Please help me find a solution.
I have a stored procedure, that checks if there is a user with the same e-mail address as the input, if not, then registeres one.
Here is the table:
CREATE TABLE IF NOT EXISTS `overkill`.`accounts` (
`accountID` INT NOT NULL AUTO_INCREMENT ,
`email` VARCHAR(64) NOT NULL ,
`firstName` VARCHAR(32) NOT NULL ,
`lastName` VARCHAR(32) NOT NULL ,
`passSaltedSHA` BINARY(20) NOT NULL ,
`salt` BINARY(20) NOT NULL ,
`gender` ENUM('m','f') NOT NULL ,
`birthDate` DATE NOT NULL ,
`regTime` TIMESTAMP NOT NULL ,
PRIMARY KEY (`accountID`) )
ENGINE = InnoDB;
Here is the stored procedure:
DELIMITER $$
CREATE PROCEDURE `overkill`.`registerUser` (
IN emailIN VARCHAR(64),
IN passwordIN VARCHAR(16),
IN firstNameIN VARCHAR(32),
IN lastNameIn VARCHAR(32),
IN birthIN DATE,
IN genderIN ENUM('f','m'))
BEGIN
DECLARE existingMailAccLOG INT DEFAULT NULL;
DECLARE saltLOC CHAR(40);
DECLARE regSuccessLOC BOOLEAN DEFAULT FALSE;
SELECT COUNT(*) INTO existingMailAccLOG FROM `overkill`.`accounts` WHERE `accounts`.`email` = emailIN;
IF existingMailAccLOG = 0 THEN
SET saltLOC = SHA1(rand());
SET regSuccessLOC = TRUE;
INSERT INTO `overkill`.`accounts` (`email`, `firstName`, `lastName`, `passSaltedSHA`, `salt`, `gender`, `birthDate`) VALUES(emailIN, firstNameIN, lastNameIn, UNHEX(SHA1(CONCAT(passwordIN, saltLOC))), UNHEX(saltLOC), genderIN, birthIN);
END IF;
SELECT regSuccessLOC AS `registered`, saltLOC AS `salt`;
END
If I call:
CALL registerUser("abc#def.com", "pass", "firstn", "lastn", "2012-01-01", "f");
It inserts a line into the accounts table, but forgets to return the proper values that I set inside the IF
SET saltLOC = SHA1(rand());
SET regSuccessLOC = TRUE;
How is it even possible? Why are theese lines skipped and INSERT still gets executed, without mistake?
Try to add "#" in front of your variable names after DECLARE keyword. It can cause some confusion, as it is described here: MySQL: #variable vs. variable. Whats the difference? (Part2) and here: MySQL: #variable vs. variable. Whats the difference?
I'm trying to write a mySQL procedure with a cursor to calculate a fare. I pass in the stationid's then I figure out what zone they are in. The fare is a set value of $1 and an additional $0.20 for each zone traveled in.
The code I have so far runs but there is a problem with the cursor not fetching the values into the variables.
Any help would be greatly appreciated. Thanks
Tables:
DROP DATABASE IF EXISTS luasSystem;
CREATE DATABASE luasSystem;
USE luasSystem;
CREATE TABLE IF NOT EXISTS line
(
line_id INT NOT NULL AUTO_INCREMENT,
Line_colour CHAR(10) NOT NULL,
PRIMARY KEY (line_id)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS zone
(
zone_id INT NOT NULL AUTO_INCREMENT,
zone_name VARCHAR(20) NOT NULL,
line INT NOT NULL,
PRIMARY KEY (zone_id),
FOREIGN KEY (line) REFERENCES line(line_id) ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS station
(
station_id INT NOT NULL AUTO_INCREMENT,
station_name CHAR(20) NOT NULL,
service CHAR(20),
line INT NOT NULL,
zone INT NOT NULL,
PRIMARY KEY (station_id),
FOREIGN KEY (line) REFERENCES line(line_id) ON UPDATE CASCADE ON DELETE RESTRICT,
FOREIGN KEY (zone) REFERENCES zone(zone_id) ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB;
Stored Procedure:
DROP PROCEDURE IF EXISTS calculateFare;
DELIMITER //
CREATE PROCEDURE calculateFare
(
IN stationid1 INT, IN stationid2 INT
)
BEGIN
DECLARE zoneNum1 INT;
DECLARE zoneNum2 INT;
DECLARE num INT;
DECLARE fare DOUBLE;
DECLARE tableEnd BOOLEAN;
DECLARE zoneCur CURSOR FOR
SELECT zone, zone FROM station
WHERE station_name = stationid1 AND station_name = stationid2;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET tableEnd = TRUE;
OPEN zoneCur;
the_loop: LOOP
FETCH zoneCur
INTO zoneNum1, zoneNum2;
IF tableEnd THEN
CLOSE zoneCur;
LEAVE the_loop;
END IF;
SET fare = 1;
SET num = 0;
IF zoneNum1 < zoneNum2 THEN
SET num = zoneNum2 - zoneNum1;
ELSEIF zoneNum1 > zoneNum2 THEN
SET num = zoneNum1 - zoneNum2;
END IF;
SET fare = (num * 0.20) + 1;
SELECT fare;
END LOOP the_loop;
END //
DELIMITER ;
CAll calculateFare(3,5);
Wouldn't this be easier of you used decimal values instead of integers? Suggest you look at : http://dev.mysql.com/doc/refman/5.0/en/fixed-point-types.html