mySql – How to search for available IDs - mysql

I have a mySQL table, which stores data of a user list and has an ID in unsigned tiny-int format (0 to 255 entries possible) as primary key. I enabled auto-increment in order to automatically set the key, which works fine so far.
When users log off I call ALTER TABLE sj_userlist AUTO_INCREMENT=1 which executes without errors.
However, the next logged in user still receives the ID+1 of the currently highest ID.
Example:
10 Users are online with the IDs 1,2,3,4,5,6,7,8,9,10
Users 1 and 2 to 9 log out - only ID 1 and 10 are still logged on
a new user logs in and receives ID 11 but I want him/her to get the 2
In case this behavior is correct, how can I achieve an alternative solution, which always starts at 1 incrementing untl the next available ID is found ?
Thanks in advance,
best
Alex

Possible solution.
Create a table for users registration. Define username column as unique.
Insert max amount of records into it according the datatype (0-255, for example).
When the user logs in and needs to register you use
UPDATE table
SET name = 'Current user name'
WHERE name IS NULL
ORDER BY id
LIMIT 1;
SELECT id
FROM table
WHERE name = 'Current user name';
This guarantee that user will get the least available number, and no interference/concurrence problems will occur.
When user log out then you use
UPDATE table
SET name = NULL
WHERE name = 'Current user name'
id is now free for re-use by the next user logged in.
If some problems occures on the client side, and user have not logged out correctly then his name will stay registered. But when he logged in the next time he will receive the same id - UPDATE will fail but SELECT will return non-freed id.
Nevertheless you must clear such old records periodically.

Related

Is it possible to limit the auto-increment value to a certain number

I am Experimenting with PHPMyAdmin database management software. I have assigned a 10 digit number to the first user and set it to AI (Auto increment). Now I want to limit the AI number to a certain number. For example " I have a number 5132400200 assigned to the first user in my table and I have set this number to auto increment so that whenever new user signup the number increments by 1 and in this case the number would be 5132400201 and so on. Now I want another table of product id and I want to begin the product id at some number like 7132400200, and whenever a new product is added the id is incremented by one. Now the difference of customer id and product id is 2000000000 (2 billion). So I practice there is no way that the user id will surpass the product id and cause chaos in the database management system. But still, for some reason, I want to limit the incrementing values of users to some extent so that I can reserve 5132400200 - 7132400199 only for User Id and 7132400200 to 8132400200 for product id. "
Create prosedure for user table check before insert if user id >= 7132400199 raise error user has reach limit.
But from business logic it self if we limit number of our customer is a stupidity.

MySQL update table 1 with table 2 data

Sorry for the ambiguous title.
I have two tables:
table 1: mailing_email
table 2 (dynamic table but for now is): membership
table 1 contains a list of all email accounts in the database and few ancillary fields such as name. It also has a column called communicate.
communicate is basically my terminology for subscribed. Any unsubscribe link will set communicate to false.
Both mailing_email and membership have a email and communicate column.
I need to write a query where the following happens:
mailing_email.communicate gets updated to the current status of membership.communicate where mailing_email.email = membership.email. If an email exists in mailing_email which does not exist in membership, the communicate field stays the same.
How would i go about doing this the fastest possible way? Each table will have thousands of rows this sync command would run often.
MySQL offers an update join syntax:
UPDATE mailing_email
JOIN membership ON mailing_email.email = membership.email
SET mailing_email.communicate = membership.communicate

How to store data like as facebook's "likes"

I have object which store in database, it's a some text with properties.
That text has rating. I need to store this rating, and prevent to one user raise this raiting more than one time. If I store "text id" and "user id" in other table and count all records which have needing "text id" i have too much records in table.
There are two ways:
You can use many-to-many relationship ie use separate table with name like 'user_likes', it will have user_id and like_id columns, both of them are primary key (it makes possible user to like the like_object only once)
Another way - which hightraffic websites use: every user record in user table has columns: likes which is just serialized array or json, whatever. Before update this columns your application retrieve this data and look for particular like_object_id if it doesn't exist - you update your database. Please note that in this case all care about data consistency in your application (for instance like_object_id exists in some user record, but doesn't exist in like_object table) should be implemented in your application code, not database.
P.S. Sorry for my english, but I tried to explain as best as I could.
If I store "text id" and "user id" in other table and count all records which have needing "text id" i have too much records in table.
How do you know what is too many records?
Some of the MySQL tables I support have billions of rows. If they need more than that, they split the data to multiple MySQL servers. 1 million rows is not a problem for a MySQL database.
If you want to limit the data so each user can "like" a given text only once, you must store the data separately for each user. This is also true if a user can "unlike" a text they had previously liked.
CREATE TABLE likes (
user_id BIGINT UNSIGNED NOT NULL,
post_id BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (user_id, post_id),
KEY (post_id, user_id)
);
This example table uses its primary key constraint to ensure each user can like a given post only once. By adding a second index, this helps to optimize queries for likes on a specific post.
This is only 16 bytes per row, plus the size of the index. I filled an InnoDB table with over 1 million rows, and it uses about 60MB.
mysql> show table status\G
Name: likes
Engine: InnoDB
Rows: 1046760
Data_length: 39419904
Index_length: 23658496
It's common to store databases on terabyte-sized storage these days, so a 60MB table doesn't seem too large.
I store the likes with the post itself, but not sure with its performance since non of my websites reached a very heavy load.
but I do the following :
Post {
id int;
likes_count int; // likes count to quickly retrive it
likes string; // id of the users liked this post, comma separated
}
when a user likes a post, (using ajax):
the UI will update directly and show that the user liked the post
ajax will send request to the server with the post id and the user id, then post data will be updated as follow:
post.likes_count += 1;
post.likes += userId + ',' ;
when the user reload the page, it will check if his id is in likes, then it the post will appear as liked.

Database design: users and guests

I have two types of people on my site, users and guests. Virtually they are the same, except for creation/auth processes.
At the moment I have two tables:
t_users
userId[PRIMARY, AUTOINC] username[UNIQUE]
t_guests
guestId[PRIMARY, AUTOINC] userId
When somebody enters the site, script does the following:
1) creates new guest record by inserting a new row to t_guests
2) adds new record to t_users, using guestId generated on previous step (guest username = “Guest guestId”)
3) updates guest record setting userId assigned on step 2
I feel this database design to be just awful, because it contains many vulnerabilities. For example, if username "Guest xyz" already exists in t_users table, step 2 will fail and step 3 will assign wrong value to the userId (depending on implementation it’ll be 0 or guestId, assigned on step 1).
Actually I only need t_guests table for its auto increment feature to generate unique usernames for guests. Is there a way to use just one consolidated table and register guests using single query?
UPDATE: I can do the following to insert guests in a single table:
SELECT #mg := IFNULL(MAX(guestId), 0) + 1 FROM t_users;
INSERT INTO t_users (guestId) VALUES(#mg);
But I can't be sure, that nobody inserts a new guest record in t_users between execution of those two statements. And I can't make guestId unique, because real users will have it equal to zero.
If you just have 1 table with"
userID, username, type
for the username you could use your script to generate a Guid and use that as the username, or someother random variable. If you use a GUID it is virtually impossible that you get 2 guids that collide.
Also if you do have 2 usernames that collide if you make sure that the username column has to be unique then the insert will fail and you could just try again.
You definitely aught to just have 1 table here.

Unique constrain with condition MYSQL

I have User table in my DB.
A user has the fields name, company_id and status: boolean, 1- live, 0- deleted.
When a user is deleted, his status is set to 0.
The combination of a live user name in a company should be unique. After a user is deleted, I don't mind that a user should be created with the same name for the company.
My question is how do I define a uniuqe constrain for the fields name, company_id and status=1 (It's not a uniuqe constrain on those three field becuase I don't mind that the combination of name-company_id-0 will appear a few times in the table).
Thanks,
Dvora
Use NULL value for deleted users.
Unique key allows unlimited number of NULL values.
Update: Don't touch user name, NULL in status field is enough.
Which programming language you are using?
your logic shoule be as follows
select * from Table_name where name='' AND company_id = '' AND status = 1
if this return any rows give uniqueness error to the user else create it.
I would create another column to store a deleted user's previous name and set their real name to NULL when they're deleted (as well as setting the status to 0).
Then have a unique constraint on name and company. NULLs will not affect the uniqueness (since NULL != NULL) and you can still recover the user's original name if desired.
So the delete operation is something like:
update users
set prev_name = name,
name = null,
status = 0
where name = 'paxdiablo' and company = 'SmallGreen';
Would it be easier if you split "live" and "deleted" so they have their own tinyint/boolean columns ?
I would replace status field with deleted_at (datetime). When the user is active its value would be NULL, but when deleted, it would be set to current datetime.
Next, i would add unique index on username & deleted_at fields, which will allow me to delete more than one user with the same username (in at least 1 second interval).