$db->query("SELECT * FROM ".DB_PREFIX."users WHERE uid='".$uid_id."' AND login='ExpressCheckoutUser'");
if ($db->moveNext())
{
$db->assignStr("address1", $_REQUEST['address_street']);
$db->assignStr("city", $_REQUEST['address_city']);
$db->assignStr("state", $_REQUEST['address_state']);
$db->assignStr("fname", $_REQUEST['first_name']);
$db->assignStr("lname", $_REQUEST['last_name']);
$db->assignStr("email", $_REQUEST['payer_email']);
$db->assignStr("country", $country_code);
$db->assignStr("zip", $_REQUEST['address_zip']);
$db->update(DB_PREFIX."users", "WHERE uid='".$uid_id."'");
$db->reset();
}
everytime i make payment via paypal, my info will be captured in database but i wanted to prevent duplicates. so how do i go around it? Or should I check email duplicates?
EDIT
As far as I can tell, uid is set to primary by pinnaclecart. so wouldnt it be 'dangerous' to set it to be unique instead?
First and last name are nice, but everything but unique. I know a few people that have the same name I do, so I guess building a unique index on those two columns will only frustrate, not help. The thing that makes me unique though is that I am the only one who has both my e-mail address and password, so I think that would be a better candidate.
ALTER TABLE users ADD UNIQUE unique_emailaddress ( email );
That should at least help with some of the duplicates, but not all: users may have multiple e-mail addresses (I know I do ;)), but it still better than an arbitrary combination of first and last name which isn't unique at all.
If all you need is a single UNIQUE column, you can do something like:
ALTER TABLE `users` ADD UNIQUE `lname`(fname);
If you set a column to UNIQUE it will only make that column unique, so if you have two people, one named "John Smith" and another named "Jane Smith", a UNIQUE on the lname will cause the second to fail. If you set UNIQUE keys on both first and last name fields separately, then you will fail in either case of first or last names being the same.
You will probably instead wish to add a compound key to enforce uniqueness across multiple fields combined. For this:
ALTER TABLE `users` ADD UNIQUE `unique_key`(fname,lname);
This would force a constraint in the database that would throw an error if you tried to create a duplicate record with the same first and last name.
You can throw exceptions on error, and handle these higher up in your codebase, or you can instead just see that you have an error and choose to ignore it.
Considering your last edit which says
uid is set to primary by pinnaclecart. so wouldnt it be 'dangerous' to set it to be unique instead?
In this case, don't do that. And don't do anything at all, PRIMARY KEY is UNIQUE by default, so it can not be duplicated.
Create a UNIQUE index in the database.
Related
A table in a MySQL database has a column for e-mail addresses. Ultimately the e-mail addresses are supposed to be unique and have valid formats. I'm having trouble deciding where the checking should be done and what checking is necessary.
Obviously SQL alone can't entirely validate an e-mail address but I was considering adding the NOT NULL constraint to prevent the submission of blank e-mail addresses. Since each e-mail address must be unique making the e-mail column a unique key seems reasonable, but just because a column is a unique key doesn't make it NOT NULL right? Since I'm probably going to be validating the e-mail address on the server using PHP I could just as well check to see if it's empty there.
A critical piece of information I'm making is does adding a unique key or a constraint make searches faster or slower?
For a column that holds e-mail addresses where there should be no duplicates and no empty strings/nulls etc. should it be made a unique key and/or given a NOT NULL constraint or something else?
I'm very novice with MySQL so code samples would be helpful. I've got phpMyAdmin if it's easier to work with.
For the unique I would use ALTER TABLE USER ADD UNIQUE INDEX(``e-mail``);
For the not null I would use ALTER TABLE user CHANGE ``e-mail`` varchar(254) NOT NULL;
Another idea I had was insert a row with a null e-mail address and then make the e-mail column unique so no other null e-mail addresses can be inserted.
Adding a unique constraint will actually make searches faster, because it will index the table by this field. Based on your description of the problem, I think your alter table statements are correct.
Fields with unique indexes can still allow nulls. nulls can never be equal to anything else, including themselves, so multiple nulls are not a violation of the uniqueness constraint. You can disallow nulls in the field by specifying it as NOT NULL, however.
A unique key is a normal field index, that simply doesn't allow multiple instances of a particular value. There will be a slight slowdown on insert/update so the key can be updated, but searches will be faster, because the index can (in some cases) be used to accelerate the search.
The answers so far are good, and I would recommend using UNIQUE KEY and NOT NULL for your application. Using UNIQUE KEY may slow down INSERT or UPDATE, but it would certainly not slow down searches.
However, one thing you should consider is that just because you use UNIQUE KEY, it does not necessarily enforce unique e-mail addresses. As an example, abc#gmail.com and a.b.c#gmail.com represent the same e-mail. If you don't want to allow this, you should normalize e-mail addresses in PHP before sending them to your database.
With MySQL you have to remember that unique index depends on the collation of your whole table (in other db you can make on upper() function).
See this link:
http://sqlfiddle.com/#!2/37386/1
Now, if you use utf8_general_ci insted of utf8_bin the index creation would fail.
I have a table of projects belonging to various users:
project_id, owner_user_id, project_name
I do not need the project_names to be globally unique to the table, so making project_name UNIQUE does not help. I would just like to prevent the user from creating duplicate project_names on INSERT or UPDATE.
Upon INSERT/UPDATE, I simply want to check if there is already a project_name belonging to a specific owner_user_id, and if it already exists, the INSERT/UPDATE should fail.
I could use a SELECT to first check for existence of the project_name within the user's projects, and then only do an INSERT/UPDATE if the select returns no results. But this is multi-threaded and another thread could INSERT the same project_name immediately after I perform the SELECT but before the INSERT/UPDATE. Putting this all into a transaction feels like overkill. Is there a single query that can perform this instead?
You could add a UNIQUE constraint on the two columns as a pair:
alter table your_table add unique (owner_user_id, project_name)
That will ensure that project_name values are unique per-user. You'll want to have a look at your collation set up to make sure your project_name values are compared without regard to case. Or you could standardize the project names to title case before hitting the database.
Don't try to maintain data integrity by hand unless you have to, let the database take care of your constraints whenever possible.
This does need to be in a transaction. You need to retrieve some information ("which names are already in use?") and then act on it ("if my name is not in use, then use it"). This must be done atomically.
As you have correctly surmised, there is a race condition if the insert does not happen atomically after the check.
This is what transactions are for.
You can add a unique constraint on both fields
CONSTRAINT C_UNICITY UNIQUE (owner_user_id, project_name)
Each time you try to insert or update a record which present duplicate, you'll get a sql error
$result = mysql_query("select * from Project where owner_user_id='1';");
if (mysql_affected_rows()==0) {
$result = mysql_query("insert into Project (projectname) values ('pojectname');");
Depending on database referential integrity violations to throw errors for you to trap is not generally a preferred form of UI validation - you generally want something at a higher abstraction level anyway. But there's nothing particularly "overkill" about using transactions and UNIQUE constraints liberally to protect your data as much as your users.
My db table looks like this pic. http://prntscr.com/22z1n
Recently I've created delete.php page. it works properly but when i deleted 21th user next registered user gets 24th id instead of 21.
Is it possible to put newly registered users info to first empty row? (In this situation 21th row)
In my registration form, newly registering user can write names of existing users, and be friends with them after registration. For this friendship i have another table that associates id of newly registered user and existing user.
For this purpose i'm using mysql_insert_id during registration to get id for new user. But after deletion of 21th row during nex registration process mysql_insert_id gave me number 21. but stored in 24th row. And put to associations table 21 for new user. I wanna solve this problem
When you use an autoincrement id column, the value that the next entry will be assigned will not be reduced by deleting an entry. That is not what an autoincrement column is used for. The database engine will always increment that number on a new insert and never decrement that number on a delete.
A MySQL auto_increment column maintains a number internally, and will always increment it, even after deletions. If you need to fill in an empty space, you have to handle it yourself in PHP, rather than use the auto_increment keyword in the table definition.
Rolling back to fill in empty row ids can cause all sorts of difficulty if you have foreign key relationships to maintain, and it really isn't advised.
The auto_increment can be reset using a SQL statement, but this is not advised because it will cause duplicate key errors.
-- Doing this will cause problems!
ALTER table AUTO_INCREMENT=12345;
EDIT
To enforce your foreign key relationships as described in the comments, you should add to your table definition:
FOREIGN KEY (friendid) REFERENCES registration_table (id) ON DELETE SET NULL;
Fill in the correct table and column names. Now, when a user is deleted from the registration, their friend association is nulled. If you need to reassociate with a different user, that has to be handled with PHP. mysql_insert_id() is no longer helpful.
If you need to find the highest numbered id still in the database after deletion to associate with friends, use the following.
SELECT MAX(id) FROM registration_table;
Auto increment is a sequence key that's tracked as part of the table. It does not go back when you delete a row.
Easily, no. What you can do (but I don't suggest doing) is making an SQL function to determine the lowest number that isn't currently occupied. Or you can create a table of IDs that were deleted, and get the smallest number from there. Or, and this is the best idea, ignore the gaps and realize the database is fine.
What you want to do is achievable by adding an extra column to your table called something like user_order. You can then write code to manage inserts and deletions so that this column is always sequential with no gaps.
This way you avoid the problems you could have messing around with an auto_increment column.
It's not a good practice to reset auto_increment value, but if you really need to do it, so you can:
ALTER TABLE mytable AUTO_INCREMENT = 1;
Run this query after every delete. Auto_increment value will not be set to 1, this will set the lowest possible value automatically.
For example, I'm doing the next action:
SELECT COUNT(id)
FROM users
WHERE unique_name = 'Wiliam'
// if Wiliam don't exists then...
INSERT INTO users
SET unique_name = 'Wiliam'
The question is, I'm doing the SELECT COUNT(id) check every time I insert a new user, despite of using an unique key or not, so... if "unique_name" has an UNIQUE key it will be better for performance than using a normal key?
What you mean is a UNIQUE CONSTRAINT on the column which will be updated. Reads will be faster, Inserts will be just a bit slower. It will still be faster than your code checking first and then inserting the value though. Just let mysql do its thing and return an error to you if the value is not unique.
You didn't say what this is for, which would help. If its part of an authentication system, then why doesn't your query include the user's password as well? If it's not, a unique indexed column used to store names isn't going to work very well in a real-world system unless you are OK with having just 1 and only Wiliam in your system. (Was that supposed to be William?)
And if that name field is really unique you do not need to use COUNT(ID) in your query. If 'unique_name' is truly unique you either get an id number returned from your query or you get nothing.
You'd want something like this:
SELECT id FROM users WHERE unique_name = 'Wiliam'
No record return, no Wiliam.
An index (unique or non-unique -- I don't know what you're after here) on unique_name will improve the performance.
Your use of 'unique key' isn't very logical so I suspect you are getting confused about the nomenclature of keys, indexes, their relationships, and the purposes for them.
KEYS in a database are used to create and identify relationships between sets of data. This is what makes the 'relational' possible in a relational database.
Keys come in 2 flavors: Primary and foreign.
PRIMARY KEYS identify each row in a table. The value or values that comprise the key must be unique.
Primary keys can be made from a single column or made of several columns (in which case it is called a composite key) that together uniquely identifies the row. Again the important thing here is uniqueness.
I use MySql's auto-increment integer data type for my primary keys.
FOREIGN KEYS identify which rows in a table have a relationship with other rows in other tables. A foreign key of a record in one table is the primary key of the related record in the other table. A foreign key is not unique -- in many-to-many relationships there are by definition multiple records with the same foreign key. They should however be indexed.
INDEXES are used by the database as a sort of short-hand method to quickly look up values, as opposed to scanning the entire table or column for a match. Think of the index in the back of a book. Much easier to find something using a book's index than by flipping through the pages looking for it.
You may also want to index a non-key column for better performance when searching on that column. What column do you use frequently in a WHERE clause? Probably should index it then.
UNIQUE INDEX is an index where all the values in it must be distinct. A column with a unique index will not let you insert a duplicate value, because it would violate the unique constraint. Primary keys are unique indexes. But unique indexes do not have to be primary keys, or even a key.
Hope that helps.
[edited for brevity]
Having a unique constraint is a good thing because it prevents insertion of duplicated entries in case your program is buggy (are you missing a "for update" clause in your select statement?) or in case someone inserts data not using your application.
You should, however, not depend on it in your application for normal operation. Lets assume unique_name is an input field a user can specify. Your application should check whether the name is unique. If it is, insert it. If it was not, tell the user.
It is a bad idea to just try the insert in all cases and see if it was successful: It will create errors in the database server logs that makes it more difficult to find real errors. And it will render your current transaction useless, which may be an issue depending on the situation
I am writing a sql editor (sqlite3).
I can display a table and allow users to edit any value in the table but I now need some way of identifying the value editted. The problem is that I don't know what the primary key is and I don't think it's that good an idea to say "update table set a=b where x=123 and y=123 and z=123 and..." for all the fields that aren't "a".
I'm using jquery (and ajax) and php.
Any ideas?
If you don't know what the primary key is (or you don't know if there is an UNIQUE index), you won't have much of a choice : even if using all fields in your where clause, you might update more than one line (the one the user wanted to edit).
You really need some way to identify one precise line -- and that way is the primary key.
Maybe, just out of curiosity, you my check how phpMyAdmin does that ?
(I know it's not SQLIte, my MySQL -- but maybe the general idea could be re-used ?)
You could force the user to specify a primary key (or at least a UNIQUE) and then retrieve it with SHOW INDEX FROM table (http://dev.mysql.com/doc/refman/5.0/en/show-index.html)
If you cannot determine PK or UK column then you have to use "where x=123 and y=123 and z=123", but remember to add LIMIT 1 - then you are sure you don't edit more than one record.
It is indeed not such a good idea to issue that update '... for all the fields that aren't a'. You should include a too, along with the old value of a in the row that was edited.