What's wrong with this code? Issue with copying data across tables - sql

insert into Permission (UserID, perm, Login) select UserID, 0, Login from Users
What happens: Copy data across tables and inserts 0 as a default value for 'perm' column. However, I need to run this code every time the software creates its form. So it keeps adding everything it already have.
Workaround: DELETE FROM Permission WHERE perm=0 --before running the insert code. This will make sure not to delete users who have Perm=1 (permission to alter something).
Issue: So I run the delete code above before running the insert. But since it's a frequent routine it will double the user already contained in the table Permissions (i.e.: user Admin will have perm=0 and perm=1). Is there anyway to detect if the user already exist and skip it or something?

What you could do is
insert into Permission(UserID,perm,Login)
select UserID, 0, Login
from Users
where UserID NOT IN(select UserID from Permission);
Basically what that does is inserts them in if they aren't already there.

This will only insert records that are not already in Permission table by the combination of UserID and Login. Probably, UserID alone is enough if Login is stored as redundant (not-normalized data).
insert into Permission (UserID, perm, Login)
select U.UserID, 0, U.Login
from Users U
left join Permission P on P.UserID = U.UserID and P.Login = U.Login
where P.Login is null
The permission matrix is usually expressed in one of two ways:
bit mask - but this gets into scalability issues real quick, so your Perm field contains a mask of all "allowed" bits
UserId - PermissionId - Access (bit). This is what I assume your table has (the tuple UserId/PermissionId) and hence the LEFT JOIN form on two fields.

Sure, this will insert only records that do not have a permission record already.
INSERT INTO Permission (UserID, perm, Login)
SELECT u.UserID, 0, u.Login
FROM Users u
LEFT OUTER JOIN Permission p ON u.UserID = p.UserID
WHERE p.UserID IS NULL

Related

Select a user by their username and then select data from another table using their UID

Sorry if that title is a bit convoluted... I'm spoiled by an ORM usually and my raw SQL skills are really poor, apparently.
I'm writing an application that links to a vBulletin forum. Users authenticate with their forum username, and the query for that is simple (selecting by username from the users table). The next half of it is more complex. There's also a subscriptions table that has a timestamp in it, but the primary key for these is a user id, not a username.
This is what I've worked out so far:
SELECT
forum.user.userid,
forum.user.usergroupid,
forum.user.password,
forum.user.salt,
forum.user.pmunread,
forum.subscriptionlog.expirydate
FROM
forum.user
JOIN forum.subscriptionlog
WHERE
forum.user.username LIKE 'SomeUSER'
Unfortunately this returns the entirety of the subscriptionlog table, which makes sense because there's no username field in it. Is it possible to grab the subscriptionlog row using the userid I get from forum.user.userid, or does this need to be split into two queries?
Thanks!
The issue is that you are blindly joining the two tables. You need to specify what column they are related by.
I think you want something like:
SELECT * FROM user u
INNER JOIN subscriptionlog sl ON u.id = sl.userid
WHERE u.username LIKE 'SomeUSER'
select * from user u JOIN subscriptions s ON u.id = s.id where u.username = 'someuser'
The bit in bold is what you want to add, it combines the 2 tables into one that you return results from.
try this
SELECT
forum.user.userid,
forum.user.usergroupid,
forum.user.password,
forum.user.salt,
forum.user.pmunread,
forum.subscriptionlog.expirydate
FROM
forum.user
INNER JOIN forum.subscriptionlog
ON forum.subscriptionlog.userid = forum.user.userid
WHERE
forum.user.username LIKE 'SomeUSER'

Compare 2 tables with results as a column

I have 2 tables, Users and Admins. Users has userID, userName, and fullName. Admins has storeID and userID.
What I'm trying to accomplish is a query that would return results that list all userIDs, userNames, fullNames, and a user defined column isAdmin that would be 0 or 1 if that particular userID is found in the Admins table.
I believe it should be possible, but I'm just drawing a blank at the moment. This will be in a stored procedure so I considered just creating temporary tables for each possibility of just a regular user or only Admins and go from there. But I would really prefer if it were all in 1 temporary table.
Any help would be greatly appreciated.
select u.*, case when a.userid is null then 0 else 1 end as isadmin
from users u
left join admins a on a.userid = u.userid

SQL Insert based on role

I have a database with 3 tables:
Table 1 (Department) - This is a table with columns for departments and departmentID's
Table 2 (SecurityMap) - This is a table that maps rolenames to department ID's
Table 3 (customer info) - this is the info that is displayed to users based on their role memberships
I have all of the SELECT based on role functions working.
What I need is to figure out how to insert a specific value into the DepartmentID column within Table 3 by default, based on the users role membership. For instance, when someone is adding a new row to the database - in addition to the data they are supplying within the "add" form, I need a default value inserted into this column. If they are a member of the Marketing role, it should be a 1, if they are a member of the IT role, it should be a 2, etc...
Ideally, this would be done without any knowledge to the user that it is even happening. I would assume that I need to use an "Instead Of" trigger, but I have no idea how to proceed....
Shouldn't be too difficult:
In your app, keep track of the logged-in user and their role.
When your app saves the customer data, make sure it passes the database the role ID as well as the user-entered data (a stored procedure would be ideal here)
When the database processes the supplied data, it saves the role ID into the appropriate column.
this should work provided the rolename-column (or id) is unique in the securityMap-table otherwise the select could return more than one value, maybe you need to select the departmentId differently then.
insert into customer_info(otherdata, departmentId) values('data', (select departmentId from securityMap where rolename = 'userrole'))
Edit:
since you mentioned db_owner maybe this can help you (from http://www.sqlservercentral.com/Forums/Topic411310-338-1.aspx)
WITH CTE_Roles (role_principal_id)
AS
(
SELECT role_principal_id
FROM sys.database_role_members
WHERE member_principal_id = USER_ID()
UNION ALL
SELECT drm.role_principal_id
FROM sys.database_role_members drm
INNER JOIN CTE_Roles CR
ON drm.member_principal_id = CR.role_principal_id
)
SELECT USER_NAME(role_principal_id) RoleName
FROM CTE_Roles
ORDER BY RoleName;
you could join that with the SecurityMap-table to filter out roles like db_owner

Login DAO sql statement involving multiple joins

I am trying to create a query that will return through DAO whether the inputted username and password is correct. I'm using java for DAO implementation as well as JSF.
I have the following tables:
LOGIN: username (pk)
BUSINESS: username (fk), password
CUSTOMER: username (fk), password
What I'm trying to do is create multiple joins so that when a user goes to log in, their stored username defines what type of account they have. By pulling the username, the username is looked for in both the BUSINESS and CUSTOMER and when found, the password is then compared. I tried the following statement:
SELECT l.USERNAME
FROM ITKSTU.BUSINESS b
JOIN ITKSTU.LOGIN l
ON l.USERNAME=b.USERNAME
JOIN ITKSTU.CUSTOMER c
ON c.USERNAME=l.USERNAME
WHERE l.USERNAME='user111' AND (b.PASSWORD='aaa' OR c.PASSWORD='aaa');
Yet it returns nothing. Any possible suggestions?
I have replicated the same here and it looks like it is working. Could you check?
http://sqlfiddle.com/#!2/f253d/2
Thanks
If I understood correctly, what you need is to distinguish a user's type, whether he/she is in business table or customer table. Then, check the password correctness.
Then, again if I am not wrong, you should have an entry for all users in login table, then each one of them should take place EITHER in businees OR customer table.
Let's assume we have records such as:
INSERT INTO login VALUES ('TEST');
INSERT INTO login VALUES ('TEST2');
INSERT INTO business VALUES ('TEST','PASSWORD123');
INSERT INTO customer VALUES ('TEST2','PASSWORD1234');
I think you may solve the problem with the following query. Let's test with the user named "TEST2":
SELECT b.username AS business_user, c.username AS customer_user
FROM login l
LEFT JOIN business b ON b.username = l.username
LEFT JOIN customer c ON c.username = l.username
WHERE l.username = 'TEST2' AND (b.password = 'PASSWORD1234' OR c.password = 'PASSWORD1234');
This query will return 2 columns as you notice: first one will return null as the user is not in business table. The second one will give you the username and label it as "customer_user". Therefore, if you check each column and determine which one is null, then you will know where the user actually belongs to (either to business or customer table).
The trick here is to begin with login table ("FROM login") and use LEFT JOIN, instead of JOIN. Here is a quick tip about joins and their differences, if you need it: http://www.firebirdfaq.org/faq93/

MySql If statements

I have a simple table that logs simple events an administrator does. Nothing complicated.
One of the columns is userid, so I can reference the user's name from the users table:
SELECT u.username FROM `users` u, `history` h WHERE u.userid = h.userid
My issue is that the internal system also logs events (just like a user), but there is no userid related to the internal system. It is simply logged as zero, in the record.
Is there a way to modify the query to reflect this? I've tried a LEFT JOIN, but that doesn't let me specify "system" as the username. The other thing i can do is enter a new user into the user's table, and call it "Internal System". But I really don't want to do that.
Is it possible to do this from the query level?
Use:
SELECT COALESCE(u.username, 'SYSTEM') AS username,
FROM HISTORY h
LEFT JOIN USERS u ON u.userid = h.userid
COALESCE will return the first non-NULL value, so if you LEFT JOIN onto USERS and username is NULL--then "system" or whatever you prefer will appear.