Use multiple variables in select - mysql

I have a question about using variables.
I need to get different values from the same condition.
Is the following example correct?
Many thanks!!!!
DECLARE #var1 varchar(50)
DECLARE #var2 varchar(50)
SELECT #var1, #var2
FROM table
WHERE IF condicion1 IN (1, 2, 3)
BEGIN
SET #var1='Value1'
SET #var2='Value2'
END

You can assign values to variables in SELECT statement.
DECLARE #var1 varchar(50)
DECLARE #var2 varchar(50)
SELECT #var1 = CASE WHEN condicion1 = 1 THEN 'Value1'
WHEN condicion1 = 2 THEN 'Value1'
WHEN condicion1 = 3 THEN 'Value1' END,
#var2 = CASE WHEN condicion1 = 1 THEN 'Value2'
WHEN condicion1 = 2 THEN 'Value2'
WHEN condicion1 = 3 THEN 'Value2' END
FROM table

Related

MySql select statement with conditional where clause

I am trying to write a MySql statement with a conditional where clause.
something like this:
set #price = 5000 ;
set #city = 1324368075;
select count(*)
from property
where case when #price is not null then
price < #price
end
and (case when #city is not null then
CityId = #city
end)
the variable should be included in the query only if it is not null.
My attempts have failed so far. Any ideas?
Edited:
Sorry I spoke too soon ysth,
these two queries are supposed to yield the same count but they dont.
Edit #2: Execution plan & indexes
Here's the query:
set #CountryId = null ;
set #CityId = 1324368075 ;
set #StateProvince = null ;
set #CategoryId = null ;
set #TransactionTypeId = null;
set #Price = 5000;
SELECT
Count(*)
FROM
meerkat.property
WHERE
(CASE WHEN #CountryId IS NOT NULL THEN CountryId = #CountryId ELSE 1 END)
AND (CASE WHEN #CityId IS NOT NULL THEN CityId = #CityId ELSE 1 END)
AND (CASE WHEN #CategoryId IS NOT NULL THEN CategoryId = #CategoryId ELSE 1 END)
AND (CASE WHEN #StateProvince IS NOT NULL THEN StateProvince = #StateProvince ELSE 1 END)
AND (CASE WHEN #TransactionTypeId IS NOT NULL THEN TransactionTypeId = #TransactionTypeId ELSE 1 END)
AND (CASE WHEN #Price IS NOT NULL THEN Price <= #Price ELSE 1 END)
AND IsPublic = 1
AND IsBlocked = 0;
Thanks in advance
If no when conditions are met, case returns null. If you want each test to pass, you need to return a true value instead, so:
case when #price is not null then
price < #price
else 1 end
and ...

CASE statement after WHERE then one of several values can be NULL?

I have such select:
SELECT
*
FROM
Table Tb
WHERE
Tb.LastModificationDate BETWEEN #StartDate And #EndDate
AND Tb.var1 = #var1
AND Tb.var2 = #var2
And its possible that #var1 and #var2 can be null (or only one of them) so for now I have 3 selects for each case (real select is more complicated so I am providing example for simplify things) I am try to merge them into one select with CASE but have no luck so far - as cant understand how to include AND clause in case if one of vars are not null.
I believe it should be something like that:
SELECT
*
FROM
Table Tb
WHERE
Tb.LastModificationDate BETWEEN #StartDate And #EndDate
(CASE WHEN #var1 IS NOT NULL THEN (AND Tb.var1 = #var1)
WHEN #var2 IS NOT NULL THEN (AND Tb.var2 = #var2)
END);
any advice on that?
To use the CASE statement, you would need to remove the AND clause from the THEN portion and move it to outside of CASE so that the result is evaluated. This is because CASE can not append the criteria to the WHERE clause (THEN AND).
SELECT *
FROM Table Tb
WHERE Tb.LastModificationDate BETWEEN #StartDate And #EndDate
AND (CASE
WHEN #var1 IS NOT NULL THEN Tb.var1 = #var1
WHEN #var2 IS NOT NULL THEN Tb.var2 = #var2
END);
However, the above approach will be limited to the first "CASE #var* IS NOT NULL" that evaluates as true. So if both #var1 and #var2 are supplied, the CASE will only return Tb.var1 = #var1, and will not compare Tb.var2 = #var2.To retrieve a result when both #var1 and #var2 are NULL, ELSE true would need to added to the CASE statement.
(CASE
WHEN #var1 IS NOT NULL THEN Tb.var1 = #var1
WHEN #var2 IS NOT NULL THEN Tb.var2 = #var2
ELSE true
END);
Another approach that circumvents the first case limitation, would be to apply the criteria directly to the WHERE clause by using AND (IS NULL OR ...).
This will allow for the criteria to match under the following 4 conditions:
Not checked if both #var1 and #var2 are NULL
#var1 if supplied (Tb.var1 = #var1)
#var2 if supplied (Tb.var2 = #var2)
#var1 and #var2 if both are supplied (Tb.var1 = #var1 AND Tb.var2 = #var2)
SELECT *
FROM Table Tb
WHERE Tb.LastModificationDate BETWEEN #StartDate And #EndDate
AND (#var1 IS NULL OR Tb.var1 = #var1)
AND (#var2 IS NULL OR Tb.var2 = #var2);
Working Examples: DB-Fiddle
SELECT
*
FROM
Table Tb
WHERE
Tb.LastModificationDate BETWEEN #StartDate And #EndDate
AND ((#var1 IS NOT NULL AND Tb.var1 = #var1)
OR
(#var2 IS NOT NULL AND Tb.var2 = #var2));
I would have done this way.
Check for both #var1 and #var2 if they are NULL or equal to the value of a column:
WHERE Tb.LastModificationDate BETWEEN #StartDate And #EndDate
AND (#var1 IS NULL OR Tb.var1 = #var1)
AND (#var2 IS NULL OR Tb.var2 = #var2)

How to use IF condition in storedProcedure?

I am using a condition to lock the login account after a fixed number of attempts with the wrong password. The update portion is as follows :
loginAttempts (INT(1)) is read from login account first
DECLARE LoginAttempts INT(1);
UPDATE login SET
LOGIN_ACCOUNT_STATUS = (SELECT CASE (LoginAttempts > MaxLoginAttempts) WHEN 1 THEN 'LOCKED' ELSE 'ACTIVE' END),
LOGIN_LOGIN_ATTEMPTS = (SELECT CASE (#USER_FOUND AND #PASSWORD_CORRECT) WHEN 1 THEN 0 ELSE LOGIN_LOGIN_ATTEMPTS + 1 END),
LOGIN_LAST_LOGIN_DATE = (SELECT CASE (#USER_FOUND AND #PASSWORD_CORRECT) WHEN 1 THEN TransactionDateTime ELSE LOGIN_LAST_LOGIN_DATE END),
LOGIN_LAST_LOGIN_LOCATION = null
WHERE LOGIN_EMAIL = UserEmail;
When I set MaxLoginAttmpts at 5, the account gets locked at 11 (Greater than twice maxLoginAttempts).
If I set MaxLoginAttmpts at 2, the account gets locked at 5 (Greater than twice maxLoginAttempts).
Why is this ? Any help is appreciated.
Here I am adding the full stored procedure.
CREATE DEFINER=`pubuducg`#`%` PROCEDURE `CustomerAuthenticate`(IN UserEmail VARCHAR(100), IN PassWD VARCHAR(40), IN AccStatus VARCHAR(100),IN TransactionDateTime DATETIME, IN MaxLoginAttempts INT(1))
BEGIN
DECLARE LoginUserID INT(11);
DECLARE LoginEmail VARCHAR(50);
DECLARE LoginPassword TINYTEXT;
DECLARE LoginAttempts INT(1);
DECLARE AccountStatus VARCHAR(45);
DECLARE UserRoles VARCHAR(80);
SELECT
login.LOGIN_USER_ID,
login.LOGIN_EMAIL,
login.LOGIN_PASSWORD,
login.LOGIN_ACCOUNT_STATUS,
login.LOGIN_LOGIN_ATTEMPTS,
GROUP_CONCAT(user_role.USER_ROLE_ROLE SEPARATOR ',') AS ROLES
INTO
LoginUserID,
LoginEmail,
LoginPassword,
AccountStatus,
LoginAttempts,
UserRoles
FROM login
INNER JOIN user_role ON
user_role.USER_ROLE_USER_ID = login.LOGIN_USER_ID AND user_role.USER_ROLE_STATUS = AccStatus
WHERE login.LOGIN_EMAIL = UserEmail;
SET #USER_FOUND = found_rows();
SET #PASSWORD_CORRECT = IF((LoginPassword = PassWD AND AccountStatus = AccStatus), true, false);
UPDATE login SET
LOGIN_ACCOUNT_STATUS = (SELECT CASE (LoginAttempts > MaxLoginAttempts) WHEN 1 THEN 'LOCKED' ELSE 'ACTIVE' END),
LOGIN_LOGIN_ATTEMPTS = (SELECT CASE (#USER_FOUND AND #PASSWORD_CORRECT) WHEN 1 THEN 0 ELSE LOGIN_LOGIN_ATTEMPTS + 1 END),
LOGIN_LAST_LOGIN_DATE = (SELECT CASE (#USER_FOUND AND #PASSWORD_CORRECT) WHEN 1 THEN TransactionDateTime ELSE LOGIN_LAST_LOGIN_DATE END),
LOGIN_LAST_LOGIN_LOCATION = null
WHERE LOGIN_EMAIL = UserEmail;
SELECT
IF(#USER_FOUND AND #PASSWORD_CORRECT, LoginUserID,0) AS USER_ID,
#PASSWORD_CORRECT AS AUTHENTICATED,
#USER_FOUND AS USER_EXISTS,
AccountStatus AS ACCOUNT_STATUS,
IF(#USER_FOUND AND #PASSWORD_CORRECT, 0, LoginAttempts + 1) AS LOGIN_ATTEMPTS,
IF(#USER_FOUND AND #PASSWORD_CORRECT, UserRoles,null) AS USER_ROLES;
END

MySQL - trigger on before insert + if data already exists + enum column

I am working on a trigger that I though is quite easy and should work but it is not working.
Here is the (abstract) table structure:
PK_id | FK1_id | FK2_id | status
1 | 12 | 15 | 'ok'
status column is defined as enum('ok', 'ok_2', 'not_ok') NUT NULL with no default value.
The trigger should verify that a combination of both FKx_id values already exists and if yes it should set the status to 'ok_2', otherwise to 'ok' and if the status is set in the INSERT INTO it is not touched.
The trigger I have right now (only body!):
BEGIN
DECLARE cnt INT;
SET cnt = (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id);
IF cnt > 0 AND NEW.status IS NULL THEN
SET NEW.status = 'ok_2';
ELSEIF NEW.status IS NULL THEN
SET NEW.status = 'ok';
END IF;
END
Unfortunately this trigger sets the status always to 'ok' - please notice that the status is not part of the INSERT query (thus considered as NULL). I have previously tried this trigger body with the same result:
BEGIN
IF (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id) > 0 AND NEW.status IS NULL THEN
SET NEW.status = 'ok_2';
ELSEIF NEW.status IS NULL THEN
SET NEW.status = 'ok';
END IF;
END
and also this (with the very same result):
BEGIN
IF EXISTS(SELECT * FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id LIMIT 1) AND NEW.status IS NULL THEN
SET NEW.status = 'ok_2';
ELSEIF NEW.status IS NULL THEN
SET NEW.status = 'ok';
END IF;
END
Can anyone tell me why the first condition is never met even if I am inserting the same FKx_id combination that is already present in the table?
EDIT: I switched the condition and the result is also the same - no 'ok_2' status set:
BEGIN
DECLARE cnt INT;
SET cnt = (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id);
IF cnt = 0 AND NEW.status IS NULL THEN
SET NEW.status = 'ok';
ELSEIF NEW.status IS NULL THEN
SET NEW.status = 'ok_2';
END IF;
END
Got it.
The problem was this declaration of the status column:
status enum('ok', 'ok_2', 'not_ok') NOT NULL
which leads into status being pre-filled with the first enum's value if the status is not set in the INSERT statement. So the solution is next trigger body:
BEGIN
DECLARE cnt INT;
SET cnt = (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id);
IF cnt = 0 THEN
SET NEW.status = 'ok';
ELSEIF NEW.status = 'ok' THEN
SET NEW.status = 'ok_2';
END IF;
END
Now if I do this insert for the first time
INSERT INTO table (FK_1, FK_2) VALUES (100, 150)
the status is 'ok', if I insert this for the second time
INSERT INTO table (FK_1, FK_2) VALUES (100, 150)
the status is 'ok_2' and if I set the status explicitly like this:
INSERT INTO table (FK_1, FK_2, status) VALUES (100, 150, 'not_ok')
the status is 'not_ok'.
so, when working with enums that have no default value while are set as NOT NULL - do not expect them to be NULL on insert when omitted. The will be pre-filled probably with the first enums's value.

How to Check IF condition in Case statement of Stored procedure

I am using CASE Statement in Stored procedure. I am using like
create proc USP_new
(
#searchtype varchar(30),
#stateName char(2),
#keywords varchar(300),
#locations varchar(100),
#searchBy varchar(20),
#keywordOption varchar(5),
#jobType char(4),
#startDate varchar(20),
#endDate varchar(20),
#companyID int
)
as begin
declare #mainQuery varchar(8000)
SELECT #mainQuery = 'SELECT JobID, JobTitle, CompanyInfo, JobSummaryLong, ModifiedDate
FROM Jobs
WHERE IsActive = 1 '
IF #startDate = '' BEGIN
SELECT #mainQuery = #mainQuery + 'And ModifiedDate >= ''' + #startDate + ' 00:00:00'' '
END
SELECT #mainQuery = #mainQuery + 'And ModifiedDate <= ''' + #endDate + ' 23:59:59'''
SELECT
CASE #mainQuery
WHEN 'state' THEN 'ONE'
WHEN 'keyword' THEN 'Second'
WHEN 'company' THEN 'Third'
ELSE 'Other'
END
I want check more condition on this 'Keyword' like When Keyword and keyword is not null then
goto THEN condition..
I used like WHEN 'keyword' AND (#keyword IS NULL) THEN '' but its is giving syntax error.
IT is possible to check condition like this or any other way to check this
Thanks....
It's really hard to tell what you are trying to accomplish with this stored proc, but I think you are definitely making thing harder than they need to be. You could probably re-write this as a single query like so:
SELECT
KeywordResult = CASE
WHEN #keywords = 'state' THEN 'ONE'
WHEN #keywords = 'keyword' THEN 'Second'
WHEN #keywords = 'company' THEN 'Third'
ELSE 'Other' END,
JobID,
JobTitle,
CompanyInfo,
JobSummaryLong,
ModifiedDate
FROM
Jobs
WHERE
IsActive = 1
AND (#StartDate <> '' AND ModifiedDate >= #StartDate)
AND ModifiedDate <= #endDate + ' 23:59:59'''