Conditional sql WHERE clause based on column values - mysql

I have a table that stores users. Every user has an ID, a Name and an Access Level. The three possible Access Levels are Administrator, Manager and Simple User.
What I want is to conditionally select from this table based on the Access Level value. I demonstrate the logic bellow:
If user is Administrator, then select all users (Administrators, Managers, Simple Users)
Else if user is Manager select all Managers and all Simple Users
Else if user is Simple User select only himself
Is that possible?

Providing Access Level is an integer that increases with the actual access level:
Administrator = 3
Manager = 2
User = 1
Then
SELECT * FROM USERS
WHERE ACCESS_LEVEL <= (SELECT ACCESS_LEVEL FROM USERS WHERE ID = #ID)
And just switch the less than sign to greater than if it is opposite.
Applies to SQL-server
EDIT: To get what you want you can use something like this:
SELECT id,name FROM users where ID = #id
UNION DISTINCT
SELECT id, name from users where access_level <=
(select case when access_level = 1 then 0 else access_level end
from users where id = #id)
With a query like this you will select all users at your current access_level or lower.
Only exception if your access_level is 1 (e.g. normal user), then only your own user is selected.

In Oracle the concept is known as Row Level Security. See articles such as this or this to get you started.

You can use following code
If(access_level=='administrator'){ str query = 'select * from users';}else if(access_level=='manager'){ str query = 'select * from users where access_level!="administrator"'; }else{ str query = 'select * from users where access_level="users"'; }

Might be a little overkill, but the following stored procedure can be used to achieve what you want:
DROP procedure IF EXISTS `listAccessibleUsers`;
DELIMITER $$
CREATE PROCEDURE `listAccessibleUsers`(IN user_id INT)
BEGIN
DECLARE u_access_level INT;
-- Select the user access level
SELECT access_level
FROM users
WHERE users.id = user_id
INTO u_access_level;
-- Result for simple users
IF u_access_level = 1 THEN
SELECT id, name, access_level
FROM users
WHERE users.id = user_id;
-- Result for admistrators and managers
ELSE
SELECT id, name, access_level
FROM users
WHERE access_level <= u_access_level;
END IF;
END$$
DELIMITER ;
Example calling code:
CALL listAccessibleUsers(200);

Related

Assign Query String in a variable

In mySQL stored procedure how can I assign a Query String to a variable, so I can reuse it? In my example I will be using SELECT id FROM audit many times.
CREATE PROCEDURE my_proc()
BEGIN
UPDATE person SET status='Active' WHERE id = (SELECT id FROM audit);
SELECT COUNT(*) FROM (SELECT id FROM audit);
//Multile scenarios the `SELECT id FROM audit` will be used.
END
Something like:
CREATE PROCEDURE my_proc()
BEGIN
myVariable = SELECT id FROM audit;
UPDATE person SET status='Active' WHERE id = (myVariable;
SELECT COUNT(*) FROM (myVariable);
//Multile scenarios the `SELECT id FROM audit` will be used.
END
Is this what you are looking for? Sorry I am not sure what you need.
SELECT #myCount:= count(id) FROM audit;
select #myCount;
Based on your reply, do you need a temporary table to store the ids from the audit and re-use those on the queries?
create temporary table tbl_tmp_audit;
select id from audit;
I am assuming you need this so that you won't join the whole audit columns every time on your succeeding queries.
--first query
UPDATE person AS p
INNER JOIN tbl_tmp_audit t ON p.id = t.id
SET status = 'Active';
--second query
SELECT COUNT(*) FROM tbl_tmp_audit;
Drop temporary table tbl_temp_bookings;

Mysql do not update if row does not exist

I've created a web app that lets you send money to other people (like paypal) for an University project.
For the send money webpage there's a form where an user can choose the money receiver's ID and the amount to send.
The system works with these queries:
SET #moneytosend= ? ; //amount to send
START TRANSACTION;
UPDATE users SET balance= balance- #moneytosend WHERE id = ?; //sender's ID
UPDATE users SET balance= balance+ #moneytosend WHERE id = ?; //receiver's ID
COMMIT WORK;
The problem is when the user inserts a non existing ID and the query is still executed, effectively removing money from the sender.
I'm sorry if my english is not perfect, and sorry again if there are any formatting errors.
One method is to check that the users exist in the update queries:
UPDATE users JOIN
(SELECT ? as sender_id, ? as receiver_id
) uu
ON u.id IN (uu.sender_id, uu.receiver_id)
SET balance = balance + (CASE WHEN u.id = uu.receiver_id THEN #moneytosend ELSE - #moneytosend)
WHERE EXISTS (SELECT 1 FROM users u2 WHERE u2.id = uu.sender_id) AND
EXISTS (SELECT 1 FROM users u2 WHERE u2.id = uu.receiver_id);
This logic combines the queries into a single query and still allows you to input only two parameters.
The problem is caused in the 1st update statement and it can be solved by adding EXISTS as a condition:
update users
set balance = balance - #moneytosend
where
balance >= #moneytosend
and
id = ? <-- sender id
and
exists (
select 1 from (select * from users where id = ? <-- receiver id
) t);
See the demo
As suggested by Raymond Nijland, do an extra check so that balance does not get a negative value.

IF user type = 1 then select form table 1 else select form table 2

i need a mysql query that can query the result like
if user type =1 then select form table one else select form table 2
please help me to build this query
i got the answer
here is the solution
SELECT IF(UserType = 1,(select Name from Users where UserID = 1),(select Name from Admin where AdminID = 1)) FROM Messages

UPDATE using SELECT as WHERE

I want to run an Update where the WHERE statement consists of 2 SELECTS, is this at all close to how you do that?
UPDATE Requests SET Response=1 WHERE
sender=SELECT userID FROM Users WHERE Username=?) and
Reciever = SELECT userID FROM Users WHERE Username=?
Thank!
You're missing parentheses, that's all.
UPDATE Requests SET Response=1 WHERE
sender = (SELECT userID FROM Users WHERE Username=?) and
receiver = (SELECT userID FROM Users WHERE Username=?);

How to get details from another table using comma operator in mysql

I have 2 tables customer,category
category:
category_id category_name vendor_id
1 laptops 10
2 bikes 10
3 cars 10
customer:
user_name password assigned_categories vendor_id
nag 12345 1,2,3 10
When I login with user_name and password ...I need to get all category_id, category_name's from category.but am getting only first category details like
category_id=1,category_name=laptops
Your customer table does not abide by the First Normal Form because you are storing multiple values in the assigned_categories attribute. If you would create a new table customer_assignments, it could all be easily done with basic SQL commands.
Here's how the new table customer_assignments would look:
user_name (FK)
category_id (FK)
PRIMARY KEY(user_name, category_id)
Many-to-Many relationships should be handled like this, not by adding multiple values into one attribute.
You could then extract your required information with a query like:
SELECT category_id, category_name
FROM (category NATURAL JOIN customer_assignments) NATURAL JOIN customer
WHERE user_name = your_current_user_name
If you are not changed your structure then below query will help you to get the your required result
DECLARE #Test VARCHAR(MAX) = ''
SELECT SET #Test = assigned_categories FROM customer WHERE user_name = 'nag'
IF LEN(#Test) > 0
BEGIN
CREATE TABLE #Temp(category_id VARCHAR(MAX))
WHILE LEN(#Test) > 0
BEGIN
IF CHARINDEX(',',#Test) > 0
BEGIN
INSERT INTO #Temp VALUES(LEFT(#Test,CHARINDEX(',',#Test)-1))
SET #Test = SUBSTRING(#Test,CHARINDEX(',',#Test) + 1,LEN(#Test))
END
ELSE
BEGIN
INSERT INTO #Temp VALUES(#Test)
SET #Test = ''
END
END
SELECT * FROM category INNER JOIN #Temp ON category.category_id = #Temp.category_id
END
maybe using SQL IN operator may help, which allows you to specify multiple values in a WHERE clause.