salesman
========
uId
salesGroupLinked
================
uId
groupId
//add performacesScore field here
group
======
groupId
I have 3 table above that formed many to many relationship, and I would add a field 'performaces' (INT) so that each salesman can have a score in each group. And I believe it should be located at salesGroupLinked table. But since uId and groupId is FK, I can't insert / edit the data (I'm using phpmyadmin). I can't make the performacesScore field unique since they can be same value for example a salesman get 10 and another get the same.
I got this msg :
This table does not contain a unique column. Grid edit, checkbox,
Edit, Copy and Delete features are not available.
describe salesGroupLinked
The tool is simply telling you that there can be several entries for a uId-groupId combination. Example:
uId groupId performacesScore
1 1 10
1 2 20
2 1 30
2 1 30
2 1 40
2 2 20
Now imagine this data is shown to you and you make the first 2/1/30 a 2/1/50. What update statement could the tool sent to the dbms?
update salesGroupLinked set performacesScore = 50
where uId = 2 and groupId = 1;
This would update three records instead of one.
update salesGroupLinked set performacesScore = 50
where uId = 2 and groupId = 1 and performacesScore = 30;
This would still update two records instead of one.
So in order to properly update and delete, you must tell the dbms what makes the records unique. There are four possibilities:
If you never want to update or delete single records, leave it as is.
If you want to be able to update and there can only be one entry for a uId-groupId combination, then tell the dbms so and make uId plus groupId the primary key of your table.
If you want to be able to update and there can be duplicates for a a uId-groupId combination, but a uId-groupId-performacesScore combination will always be unique, then make these three the table's primary key.
If you want to be able to update and there can be duplicates for any combination, then give the table another column for a technical id and make this the primary key.
Related
I have a table in MySQL, which represents a user, that should be able to add up to three phone numbers to his account. So of course no phone number, that already exists should be able to be registered again. I made all three columns unique, but the problem is, that you can still enter as number 2 a number, that someone else entered as his first number. So I was wondering, if there is an SQL possibility to ensure, that one row is unique with other rows too or I need to solve this issue with querying, if there exists already a member with this number programmatically.
MemberID
Main number
Number 2
Number 3
1
123
456
789
2
456
123
567
So this example should be forbidden.
So as Strawberry assumed the best solution is to normalize the table. Since every member as 1 to n numbers, the numbers should be an own entity.
The resulting solution would be to remove the number fields out of the member table and create a new table, which looks the following:
Member_Id (Foreign Key)
Priority
Number
1
1
234
...
...
...
Then a unique constraint on the number column ensures, that no number is used by two members.
I am trying to insert multiple entries into a table. However, some of these entries may be the same to existing ones: in such scenarios, these duplicate entries should not be inserted.
Here's an example:
table
id name number
1 alice 12345
2 bob 67890
id is auto-increment, while name and number are actual data.
Say now I have 3 more entries that I want to insert in the table using one instruction:
name number
alice 12345
alice 54321
bob 67890
Since the 1st and 3rd record is already there in the table, it would be desired to ignore them in insertion. But the db will take id as a key also, which is always different for each entries. So how may I subvert this, please?
Thanks!
If the unique key is supposed to be (name, number), then put a unique index on it. If you want to skip duplicate entries, check out INSERT...IGNORE or do some serious magic with ON DUPLICATE KEY.
I have a problem with my queries in MySQL. My table has 4 columns and it looks something like this:
id_users id_product quantity date
1 2 1 2013
1 2 1 2013
2 2 1 2013
1 3 1 2013
id_users and id_product are foreign keys from different tables.
What I want is to delete just one row:
1 2 1 2013
Which appears twice, so I just want to delete it.
I've tried this query:
delete from orders where id_users = 1 and id_product = 2
But it will delete both of them (since they are duplicated). Any hints on solving this problem?
Add a limit to the delete query
delete from orders
where id_users = 1 and id_product = 2
limit 1
All tables should have a primary key (consisting of a single or multiple columns), duplicate rows doesn't make sense in a relational database. You can limit the number of delete rows using LIMIT though:
DELETE FROM orders WHERE id_users = 1 AND id_product = 2 LIMIT 1
But that just solves your current issue, you should definitely work on the bigger issue by defining primary keys.
You need to specify the number of rows which should be deleted. In your case (and I assume that you only want to keep one) this can be done like this:
DELETE FROM your_table WHERE id_users=1 AND id_product=2
LIMIT (SELECT COUNT(*)-1 FROM your_table WHERE id_users=1 AND id_product=2)
Best way to design table is add one temporary row as auto increment and keep as primary key. So we can avoid such above issues.
There are already answers for Deleting row by LIMIT. Ideally you should have primary key in your table. But if there is not.
I will give other ways:
By creating Unique index
I see id_users and id_product should be unique in your example.
ALTER IGNORE TABLE orders ADD UNIQUE INDEX unique_columns_index (id_users, id_product)
These will delete duplicate rows with same data.
But if you still get an error, even if you use IGNORE clause, try this:
ALTER TABLE orders ENGINE MyISAM;
ALTER IGNORE TABLE orders ADD UNIQUE INDEX unique_columns_index (id_users, id_product)
ALTER TABLE orders ENGINE InnoDB;
By creating table again
If there are multiple rows who have duplicate values, then you can also recreate table
RENAME TABLE `orders` TO `orders2`;
CREATE TABLE `orders`
SELECT * FROM `orders2` GROUP BY id_users, id_product;
You must add an id that auto-increment for each row, after that you can delet the row by its id.
so your table will have an unique id for each row and the id_user, id_product ecc...
I have a table with an auto_increment field and sometimes rows get deleted so auto_increment leaves gaps. Is there any way to avoid this or if not, at the very least, how to write an SQL query that:
Alters the auto_increment value to be the max(current value) + 1
Return the new auto_increment value?
I know how to write part 1 and 2 but can I put them in the same query?
If that is not possible:
How do I "select" (return) the auto_increment value or auto_increment value + 1?
Renumbering will cause confusion. Existing reports will refer to record 99, and yet if the system renumbers it may renumber that record to 98, now all reports (and populated UIs) are wrong. Once you allocate a unique ID it's got to stay fixed.
Using ID fields for anything other than simple unique numbering is going to be problematic. Having a requirement for "no gaps" is simply inconsistent with the requirement to be able to delete. Perhaps you could mark records as deleted rather than delete them. Then there are truly no gaps. Say you are producing numbered invoices: you would have a zero value cancelled invoice with that number rather than delete it.
There is a way to manually insert the id even in an autoinc table. All you would have to do is identify the missing id.
However, don't do this. It can be very dangerous if your database is relational. It is possible that the deleted id was used elsewhere. When removed, it would not present much of an issue, perhaps it would orphan a record. If replaced, it would present a huge issue because the wrong relation would be present.
Consider that I have a table of cars and a table of people
car
carid
ownerid
name
person
personid
name
And that there is some simple data
car
1 1 Van
2 1 Truck
3 2 Car
4 3 Ferrari
5 4 Pinto
person
1 Mike
2 Joe
3 John
4 Steve
and now I delete person John.
person
1 Mike
2 Joe
4 Steve
If I added a new person, Jim, into the table, and he got an id which filled the gap, then he would end up getting id 3
1 Mike
2 Joe
3 Jim
4 Steve
and by relation, would be the owner of the Ferrari.
I generally agree with the wise people on this page (and duplicate questions) advising against reusing auto-incremented id's. It is good advice, but I don't think it's up to us to decide the rights or wrongs of asking the question, let's assume the developer knows what they want to do and why.
The answer is, as mentioned by Travis J, you can reuse an auto-increment id by including the id column in an insert statement and assigning the specific value you want.
Here is a point to put a spanner in the works: MySQL itself (at least 5.6 InnoDB) will reuse an auto-increment ID in the following circumstance:
delete any number rows with the highest auto-increment id
Stop and start MySQL
insert a new row
The inserted row will have an id calculated as max(id)+1, it does not continue from the id that was deleted.
As djna said in her/his answer, it's not a good practice to alter database tables in such a way, also there is no need to that if you have been choosing the right scheme and data types. By the way according to part od your question:
I have a table with an auto_increment field and sometimes rows get deleted so auto_increment leaves gaps. Is there any way to avoid this?
If your table has too many gaps in its auto-increment column, probably as a result of so many test INSERT queries
And if you want to prevent overwhelming id values by removing the gaps
And also if the id column is just a counter and has no relation to any other column in your database
, this may be the thing you ( or any other person looking for such a thing ) are looking for:
SOLUTION
remove the original id column
add it again using auto_increment on
But if you just want to reset the auto_increment to the first available value:
ALTER TABLE `table_name` AUTO_INCREMENT=1
not sure if this will help, but in sql server you can reseed the identity fields. It seems there's an ALTER TABLE statement in mySql to acheive this. Eg to set the id to continue at 59446.
ALTER TABLE table_name AUTO_INCREMENT = 59446;
I'm thinking you should be able to combine a query to get the largest value of auto_increment field, and then use the alter table to update as needed.
Creating a mini-database with access, i came across this problem:
For the background, i have two tables:
Table: Items and Table: Actions
ID(PK) Name ID(PK) Name
------------------ ----------------
1 Thing1 1 Move
2 Thing2 2 Delete
3 Thing3
I created a query that lists available actions for each item:
Query: AvailableActions
Item_ID Action_ID
------------------------
1 2 //Thing1 can be deleted
2 1 //Thing2 can be moved
2 2 //Thing1 can be deleted
(no more records)
Now i want to populate a third table that lists the history of objects
Table: History
ID(PK) Item_ID Action_ID
----------------------------------
1 1 2
2 1 2
3 2 1
4 2 2
So i'm trying to make a lookup-field for Action_ID, where i can only pick values that are allowed for the choosed item. However, be it in design mode or SQL mode, i can't get the value of that field.
Do you have any hints?
Before you sort out the UI (mop the floor...), ensure you have the required constraint on the table (...fix the leak) e.g. ANSI-92 Query Mode SQL DDL:
ALTER TABLE History ADD
CONSTRAINT fk__history__AvailableActions
FOREIGN KEY (Item_ID, Action_ID)
REFERENCES AvailableActions (Item_ID, Action_ID);
...assuming you already have the required unique constraint on AvailableActions (Item_ID, Action_ID).
If you want a list of actions that can be applied to Item X then you can generate this with:
SELECT Actions.ID, Actions.Name FROM Actions INNER JOIN AvailableActions
ON Actions.ID = AvailableActions.ActionID WHERE Actions.Item_ID = X
When you talk about deleting "Thing 1", do you actually intend to delete the record from the table or does that record proxy for something else (like a disk file). If you actually delete it, you will have trouble establishing a PK / FK relationship between Items and AvailableActions if that was your intent.
Well as i stated in comments, the only way i achieved this goal is by adding a sub-form to the Items form. (unable to specify this with the structure only, as those Available_actions are computed depending on that same History table)