I need to convert this tSQL query into MySQL query version 5.7.14
I tried declare parameter with the following syntax
declare #commissionType INT;
but I reached a dead end and need help to convert this query
CREATE PROCEDURE MyProc
#chainId int
as
BEGIN
declare #commissionMethod int
declare #commissionType int
declare #value decimal(18,2)
set #commissionMethod = 1
set #value = 200000
set #commissionType = (select CommissionType from CommissionRules
where ChainId = #chainId )
IF(#commissionMethod = 1)
BEGIN
print('alert')
select (Fixed * #value) / 100 from CommissionRules where ChainId = #chainId
END
END
This is pretty much a literal conversion. But check your logic. It doesn't make any sense. v_commissionMethod is always 1 and v_commissionType is not even being used after selecting a value.
DELIMITER //
CREATE PROCEDURE MyProc (
p_chainId int)
BEGIN
declare v_commissionMethod int;
declare v_commissionType int;
declare v_value decimal(18,2);
set v_commissionMethod = 1;
set v_value = 200000;
select CommissionType into v_commissionType from CommissionRules
where ChainId = p_chainId ;
IF(v_commissionMethod = 1)
THEN
/* print('alert') */
select (Fixed * v_value) / 100 from CommissionRules where ChainId = p_chainId;
END IF;
END;
//
DELIMITER ;
Something like this:
DELIMITER $$
CREATE PROCEDURE MyProc (
in_chainId unsigned
) as
BEGIN
select v_CommissionType := CommissionType,
v_commissionMethod = 1,
v_value = 200000
from CommissionRules
where ChainId = in_chainId;
if v_commissionMethod = 1 then
select 'alert';
select (Fixed * v_value) / 100
from CommissionRules
where ChainId = in_chainId
end if;
END;$$
DELIMITER ;
Related
CREATE TABLE ZAMOWIENIA( id_zamowienia INT PRIMARY KEY NOT NULL,
id_uzytkownika INT, kwota_zamowienia DECIMAL(10,2));
INSERT INTO
ZAMOWIENIA VALUES (1,1,20), (2,4 ,5), (3,3,100), (4,1,300),
(5,2,80), (6, 1,150);
SELECT * FROM ZAMOWIENIA;
select
count(id_uzytkownika) from ZAMOWIENIA WHERE id_uzytkownika=1;
DROP
FUNCTION AccountType;
DELIMITER //
CREATE FUNCTION AccountType(
in_id_uzytkownika INT) RETURNS VARCHAR(20) DETERMINISTIC
BEGIN
DECLARE account_type VARCHAR(20);
DECLARE in_id_uzytkownika INT;
DECLARE zamowienia INT;
select count(id_uzytkownika) AS zamowienia
from ZAMOWIENIA
WHERE id_uzytkownika=in_id_uzytkownika;
select zamowienia from zamowienia;
IF zamowienia >10 THEN
SET account_type = 'BRONZE';
END IF;
IF zamowienia >30 THEN
SET account_type = 'SILVER';
END IF;
IF zamowienia >60 THEN
SET account_type = 'GOLD';
END IF;
return account_type;
END // DELIMITER ;
If you want to set a variable to the result of a SELECT query, you need to use SELECT ... INTO variable, not SELECT ... AS variable. Your function is trying to return the result of the SELECT query because it doesn't store the result into a variable.
Or you can use SET statement, which is simpler when you're just setting a single variable.
So replace the two SELECT statements with:
SET zamowienia = (SELECT COUNT(*) FROM from ZAMOWIENIA
WHERE id_uzytkownika=in_id_uzytkownika);
Also, you shouldn't have DECLARE statements for the function parameters. Remove the line
DECLARE in_id_uzytkownika INT;
I have tried this procedure to insert data:
CREATE PROCEDURE myproc()
BEGIN
DECLARE i int DEFAULT 30;
DECLARE acc = 'access';
WHILE i <= 80 DO
acc = acc + i + '#gmail.com';
INSERT INTO users (email, status, password) VALUES (acc, 1, '$2y$12$/Jc6ayqwr333Od/0bexYF.aT1h34mzmElG8SFozzrWjhokS6wEUA6');
SET i = i + 1;
END WHILE;
END
But problem is in line: acc = acc + i + '#gmail.com';
How to do that right in MySQL?
Also I have tried this:
CREATE PROCEDURE myproc()
BEGIN
DECLARE i INT;
DECLARE acc VARCHAR;
i = 16;
WHILE i <= 17 DO
acc = 'access' + i + '#gmail.com';
INSERT INTO users (email, status, password) VALUES (acc, 1, '$2y$12$/Jc6ayqwr333Od/0bexYF.aT1h34mzmElG8SFozzrWjhokS6wEUA6');
SET i = i + 1;
END WHILE;
END
You have not declared the type for acc and have not used a set clause to set it in the loop and you don't know how to concat in mysql and the concat you are attempting is logically wrong.
try this
drop procedure if exists p;
delimiter $$
CREATE PROCEDURE p()
BEGIN
DECLARE i int DEFAULT 30;
DECLARE acc varchar(10) default 'access';
declare vemail varchar(30);
WHILE i <= 35 DO
set vemail = concat(acc,i,'#gmail.com');
#INSERT INTO users (email, status, password) VALUES (vemail, 1, '$2y$12$/Jc6ayqwr333Od/0bexYF.aT1h34mzmElG8SFozzrWjhokS6wEUA6');
select vEmail;
SET i = i + 1;
END WHILE;
END $$
delimiter ;
call p()
When you are happy with the vemail format uncomment the insert and remove the select
I'm looking to do some validation of data replication between some different database systems, with different character sets (potentially) and a third party software that migrates the data. To help test an aspect of this, I'm looking to do something like the following.
ASCII(foo) returns the value for the first character in the string. Is there a way to get the ascii values for all characters in a string in one go, in one select statement? Something like concating the values together, separated by a space. E.g. If the string was hello then the output would be 104 101 108 108 111
Reference:
select ascii('h'); -- 104
select ascii('e'); -- 101
select ascii('l'); -- 108
select ascii('o'); -- 111
Just had the same problem, so here is a procedure that does the work:
DELIMITER $$
CREATE PROCEDURE string_to_ascii(IN inputStr VARCHAR(255))
BEGIN
DECLARE strLen INT DEFAULT 0;
DECLARE idx INT DEFAULT 0;
DECLARE current_char VARCHAR(1);
DECLARE current_char_ascii VARCHAR(10);
DECLARE outputStr TEXT;
IF inputStr IS NULL THEN
SET inputStr = '';
END IF;
SET strLen = CHAR_LENGTH(inputStr);
SET idx = 1;
WHILE idx <= strLen DO
SET current_char = SUBSTR(inputStr, idx, 1);
SET current_char_ascii = ASCII(current_char);
IF idx = 1 THEN
SET outputStr = current_char_ascii;
ELSE
SET outputStr = CONCAT(outputStr, ",", current_char_ascii);
END IF;
SET idx = idx+1;
END WHILE;
SELECT outputStr;
END
$$
DELIMITER ;
Usage:
> CALL string_to_ascii('hello');
+---------------------+
| outputStr |
+---------------------+
| 104,101,108,108,111 |
+---------------------+
If you prefer to use it as a function:
DELIMITER //
CREATE FUNCTION string_to_ascii ( inputStr TEXT )
RETURNS TEXT
DETERMINISTIC
BEGIN
DECLARE strLen INT DEFAULT 0;
DECLARE idx INT DEFAULT 0;
DECLARE current_char VARCHAR(1);
DECLARE current_char_ascii VARCHAR(10);
DECLARE outputStr TEXT;
IF inputStr IS NULL THEN
SET inputStr = '';
END IF;
SET strLen = CHAR_LENGTH(inputStr);
SET idx = 1;
WHILE idx <= strLen DO
SET current_char = SUBSTR(inputStr, idx, 1);
SET current_char_ascii = ASCII(current_char);
IF idx = 1 THEN
SET outputStr = current_char_ascii;
ELSE
SET outputStr = CONCAT(outputStr, ",", current_char_ascii);
END IF;
SET idx = idx+1;
END WHILE;
RETURN outputStr;
END; //
DELIMITER ;
And then the usage will be:
> SELECT string_to_ascii('hello');
+--------------------------+
| string_to_ascii('hello') |
+--------------------------+
| 104,101,108,108,111 |
+--------------------------+
I have the mysql version 5.5.38.
When I call a procedure that call a function inside there, handler condition its activated into function and raise up to procedure. I need that handler condition on function not affect the process on procedure. Included the function and procedure.
function:
DELIMITER $$
CREATE FUNCTION FUNCTION_HOURLY_GAS_CHANGE(INI_DATE DATETIME, TANK INT)
RETURNS INT
NOT DETERMINISTIC
BEGIN
DECLARE END_GAL INT;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET END_GAL = -1;
SET END_GAL = 0;
SELECT GALLONS INTO END_GAL
FROM TLS_TEMP_DATA WHERE FK_TANK = TANK
AND DATE LIKE CONCAT(DATE_FORMAT(DATE_ADD(DATE_FORMAT(INI_DATE, '%Y-%m-%d %H'), INTERVAL 1 HOUR), '%Y-%m-%d %H'),':%')
AND REQUEST_TYPE = 1;
RETURN END_GAL;
END $$
DELIMITER ;
procedure:
DELIMITER $$
CREATE PROCEDURE HOURLY_GAS_CHANGE(IN dateReport char(50), IN tank INT)
BEGIN
DECLARE COMPLETELOOP INT DEFAULT 0;
DECLARE INI_DATE DATETIME;
DECLARE INI_GAL INT;
DECLARE END_GAL INT;
DECLARE DIFF INT;
DECLARE V_HOUR CHAR(50);
DECLARE V_INI_GAL CHAR(50);
DECLARE V_END_GAL CHAR(50);
DECLARE V_DIFF CHAR(50);
DECLARE INITIALDATA CURSOR FOR
SELECT
DATE, GALLONS FROM TLS_TEMP_DATA WHERE FK_TANK = tank
AND (DATE BETWEEN CONCAT(dateReport, ' 00:00:00') AND CONCAT(dateReport, ' 23:59:59')) AND REQUEST_TYPE = 1
ORDER BY ID;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET COMPLETELOOP = 1;
DROP TEMPORARY TABLE IF EXISTS HOURLYGASCHANGE;
CREATE TEMPORARY TABLE HOURLYGASCHANGE(
`HOUR_DATA` CHAR(50) NOT NULL,
`INI_GAL` CHAR(50) NOT NULL,
`END_GAL` CHAR(50) NOT NULL,
`DIFF` CHAR(50) NOT NULL)
ENGINE=MEMORY;
OPEN INITIALDATA;
READ_LOOP: LOOP
FETCH INITIALDATA INTO INI_DATE, INI_GAL;
IF COMPLETELOOP THEN
LEAVE READ_LOOP;
END IF;
SET END_GAL = 1;
SET END_GAL = FUNCTION_HOURLY_GAS_CHANGE(INI_DATE, tank);
IF END_GAL > 0 THEN
SET DIFF = (END_GAL - INI_GAL);
SET V_DIFF = CAST(DIFF AS CHAR(50));
SET V_END_GAL = CAST(END_GAL AS CHAR(50));
ELSE
SET V_DIFF = 'N/A';
SET V_END_GAL = 'NOT UPDATED';
END IF;
SET V_INI_GAL = CAST(INI_GAL AS CHAR(50));
SET V_HOUR = CAST(DATE_FORMAT(INI_DATE, '%H') AS CHAR(50));
INSERT INTO HOURLYGASCHANGE VALUES(V_HOUR, V_INI_GAL, V_END_GAL, V_DIFF);
END LOOP;
close INITIALDATA;
SELECT * FROM HOURLYGASCHANGE;
END $$
DELIMITER ;
I can't fix the problem, but I found a solution to replace the function, I capture empty result into IFNULL function and now I can set a specific value when select show me a empty result.
SELECT (
IFNULL(
(
SELECT ENDTLS.GALLONS
FROM TLS_TEMP_DATA ENDTLS
WHERE ENDTLS.FK_TANK = tank
AND ENDTLS.DATE LIKE ONCAT(DATE_FORMAT(DATE_ADD(DATE_FORMAT(INI_DATE, '%Y-%m-%d %H'), INTERVAL 1 HOUR), '%Y-%m-%d %H'),':%')
AND ENDTLS.REQUEST_TYPE = 1
)
, -1)
) INTO END_GAL;
This procedure does not return 2, it always returns 1. How to return 1 when insert happens, and return 2 when an update happens?
It is perfectly insert and update but return value always 1.
CREATE PROCEDURE [dbo].[sp_SaveEmployeeDetails]
#employeeID int
,#first_name varchar(255)
,#middle_name varchar(255)
,#last_name varchar(255)
,#gender varchar(255)
,#date_of_birth date
,#EntryBy varchar(255)
--,#ActionStatus int = NULL OUTPUT
AS
BEGIN
SET NOCOUNT OFF;
DECLARE #ActionStatus int;
IF NOT EXISTS(Select * From employees
Where employeeID =#employeeID)
BEGIN
INSERT INTO [dbo].[employees] ([first_name], [middle_name], [last_name], [gender], [date_of_birth], [EntryBy], [EntryDate])
VALUES (#first_name, #middle_name, #last_name, #gender, #date_of_birth, #EntryBy, getdate())
SET #ActionStatus = 1;
END
ELSE
BEGIN
UPDATE employees
SET [first_name] = #first_name,
[middle_name] = #middle_name,
[last_name] = #last_name,
[gender] = #gender,
[date_of_birth] = #date_of_birth,
[EntryBy] = #EntryBy,
[EntryDate] = getdate()
WHERE
employeeID = #employeeID
SET #ActionStatus = 2;
END
RETURN #ActionStatus;
--also try SELECT #ActionStatus;
END
The value you return here
RETURN #ActionStatus;
...might be set to a variable directly, its the procedure's "own" return value. Look at this example:
CREATE PROCEDURE dbo.TestReturn(#IntValue INT)
AS
BEGIN
IF #IntValue=0
RETURN 0;
ELSE
RETURN 1;
END
GO
DECLARE #RetVal INT;
EXEC #RetVal = dbo.TestReturn -1;
SELECT #RetVal;
EXEC #RetVal = dbo.TestReturn 0;
SELECT #RetVal;
EXEC #RetVal = dbo.TestReturn 1;
SELECT #RetVal;
GO
DROP PROCEDURE dbo.TestReturn;
It comes back with 1-0-1 as expected.
But this return value is bound to INT and is meant to reflect execution states (like error codes, success level...) In your case this seems to be the case...
If you think about output of any other data use OUTPUT parameters.
CREATE PROCEDURE dbo.TestReturn(#IntValue INT, #TestPrm VARCHAR(100) OUTPUT)
AS
BEGIN
IF #IntValue=0
BEGIN
SET #TestPrm='Value was 0'
RETURN 0;
END
ELSE
BEGIN
SET #TestPrm='Value was something else';
RETURN 1;
END
END
GO
DECLARE #RetVal INT;
DECLARE #RetVarchar VARCHAR(100);
EXEC #RetVal = dbo.TestReturn -1,#RetVarchar OUTPUT;
SELECT #RetVal,#RetVarchar;
EXEC #RetVal = dbo.TestReturn 0,#RetVarchar OUTPUT;
SELECT #RetVal,#RetVarchar;
EXEC #RetVal = dbo.TestReturn 1,#RetVarchar OUTPUT;
SELECT #RetVal,#RetVarchar;
GO
DROP PROCEDURE dbo.TestReturn;