A table contains the following data, is using INNODB, has a UNIQUE constraint on position/fk, and doesn't allow NULL for position.
+----+----------+-----+
| id | position | fk |
+----+----------+-----+
| 1 | 1 | 123 |
| 2 | 2 | 123 |
| 3 | 3 | 123 |
| 4 | 4 | 123 |
| 5 | 5 | 123 |
| 6 | 6 | 123 |
| 7 | 7 | 123 |
| 8 | 8 | 123 |
| 9 | 9 | 123 |
| 10 | 10 | 123 |
+----+----------+-----+
PHP receives a request to update the table to the following. The format of the request can be provided how ever is most convenient such as [2,1,4,3,6,5,8,7,10,9] or [{"id":1, "position":2}, ... ], etc.
+----+----------+-----+
| id | position | fk |
+----+----------+-----+
| 1 | 2 | 123 |
| 2 | 1 | 123 |
| 3 | 4 | 123 |
| 4 | 3 | 123 |
| 5 | 6 | 123 |
| 6 | 5 | 123 |
| 7 | 8 | 123 |
| 8 | 7 | 123 |
| 9 | 10 | 123 |
| 10 | 9 | 123 |
+----+----------+-----+
I've confirmed that SET unique_checks=0; will not allow unique checks to be temporarily disabled, and don't wish to actually remove the unique index, update the table, and reapply the unique index.
How can this table be updated?
If there is no simple means to do so, I thought of a couple of options, but don't like them:
Allowing NULL in position. Is there a way to temporarily allow NULL similar to how SET FOREIGN_KEY_CHECKS=0; can disable foreign keys?
First delete all the records and then reinsert them. This might result in performance issues as there are indexes on the table which will need to be recreated.
All I can think is that you need to first change all the positions to some other values that aren't in the range of new position values you ultimately need to set, but are still unique within the rows.
An easy way to do this, assuming your position column is a signed integer, is to set all the positions to their opposite (negative) value. They'll remain unique, but they won't be in the set of the new values.
You can do this in a transaction along with your subsequent updates, so no other concurrent transaction will ever see the negative values.
BEGIN;
UPDATE MyTable SET position = -position;
UPDATE MyTable SET position = 2 WHERE id = 1;
...etc...
COMMIT;
This is a hack. The sign bit of the integer is being used for a purpose other than showing negative numbers.
Related
Ok, I have a single MySQL table with the name 'car' and 3 columns.
+----+--------+------------+
| ID | car_id | engine |
+----+--------+------------+
| 1 | 123 | on |
| 2 | 123 | on |
| 3 | 123 | off |
| 4 | 123 | on |
| 5 | 123 | on |
| 6 | 123 | on |
| 7 | 123 | off |
| 8 | 123 | on |
| 9 | 123 | off |
+----+--------+------------+
Now I want to show the trips this car did. The trips would be determined based on car engine start and stop. For example from the above example we can see that user has made 3 trips as total(From on to off). Now What I want is that if there is a query which gives me only 3 results from on to off meaning if somehow the query groups the records by considering a starting point on and ending point off. Is it possible in mysql? or the other way around is doing it manually by fetching all the records and working in arrays?
At the moment I am fetching all the records and doing it manually by looping all the data and doing accordingly But this process is slow.
Can you try it ?
SELECT * from cars WHERE `engine` = 'off' AND id IN(SELECT id+1 FROM `cars` WHERE `engine` = 'on')
I have a search page that allow user to key in the member ID and it will list out all the downline that belongs to the user.
I am using easyui treegrid to generate the downline.
Now i need to do an extra button to export out all the downline that belongs to the search id and export each line of information into excel file.
This is part of my data, and actually the real data had more column and about 4000++ of data.
Is there anyone can help me or some references? Please let me know if you need more info
+-------------+---------------+---------------------------+------------+
| MemberID | parent_id | Name | Age |
+-------------+---------------+---------------------------+------------+
| 1 | 0 | Cassy | 8 |
| 2 | 1 | Peter | 7 |
| 3 | 1 | Maide | 7 |
| 4 | 1 | Samda | 7 |
| 5 | 4 | Kinso | 7 |
| 6 | 4 | March | 7 |
| 7 | 2 | Sandy | 10 |
| 8 | 0 | Mandy | 12 |
+-------+---------------+----------------------------------------------+
I have a PHP Based App that stores invoices entered by the user. Currently I have the invoice amount stored in a MySQL database tables as a double like so:
+------+--------------+--------------+----------------+----------------+-------------+-----------+---------------+-------------+-------------+-----------------+
| id | date_entered | invoice_date | invoice_number | invoice_amount | client_type | unique_id | supplier_type | supplier_id | category_id | childcare_hours |
+------+--------------+--------------+----------------+----------------+-------------+-----------+---------------+-------------+-------------+-----------------+
| 1 | 1411098397 | 1411048800 | 123 | 0.01 | 0 | 137 | 0 | 139 | 5 | NULL |
| 2 | 1412123404 | 1416920400 | 5093 | 130 | 0 | 168 | 0 | 19 | 18 | NULL |
| 3 | 1412125933 | 1412085600 | 000 | 79 | 0 | 151 | 0 | 177 | 8 | NULL |
| 4 | 1412645652 | 1412600400 | 000 | 60.8 | 0 | 104 | 0 | 179 | 9 | NULL |
| 5 | 1412647563 | 1409320800 | 804560 | 225.5 | 0 | 18 | 0 | 174 | 10 | NULL |
I am also using DataTables toorganise the data. I am using Server Side Processing to perform the data lookup to return as JSON.
The issue I am having is that the User is attempting to search by price eith by typing $123 or 123.50 This is not working as the SQL is being genrated like so: SELECT * FROM invoices WHERE invoice_amount LIKE "%$123%";
This is obviosuly failing due to the data being stored in the database as a double.
My Question is, is there a way to make the SQL (or Maybe PHP) search for the correct value no matter what the client types in?
I don't think there is any generic solution for the problem that you are facing but yeah you can remove the special characters like $ etc. from the beginning or end of the invoice amount to be placed in the query. Moreover I'll recommend that you should use functions as round in PHP as well as MySQL in the best possible fashion rather than using the LIKE statement. Using LIKE statement is absolutely incorrect in this situation.
You can try query without "$"
SELECT * FROM invoices WHERE invoice_amount LIKE "%123%";
Okay so I'm creating a task manager for my company. A user can assign assign a task to multiple other users. So I've though of 2 ways of implementing this.
This is my tasks table for option one (at least the columns that are important in this discussion ):
----------------------------------------------
| id | assigned_to | assigned_from |
---------------------------------------------
| 1 | 1,3,6 | 4 |
--------------------------------------------
| 2 | 1,4 | 2 |
---------------------------------------------
So here I pretty much just comma separate each user_id that is assigned to this particular task
Option 2:
----------------------------------------------------------
| id | task_id | assigned_to | assigned_from |
------------------------------------------------------------
| 1 | 335901 | 1 | 4 |
-----------------------------------------------------------
| 2 | 335901 | 3 | 4 |
-----------------------------------------------------------
| 3 | 335901 | 6 | 4 |
-----------------------------------------------------------
| 4 | 564520 | 1 | 2 |
-----------------------------------------------------------
| 4 | 564520 | 4 | 2 |
-----------------------------------------------------------
So as you can see here instead of putting the assiged_to is's here I just create a task id which is a random number and then I can groupBy 'task_id'. This is currently they way I have built it but for some reason it feels like it might screw me over in the future (not that option one doesn't give me the same feeling). So my question is which way do you guys recommend or is there maybe a different better way that I could be doing this?
Option 2 ist the better solution since you can acutally work with the table. You may e.g. create another table Tasks with
Task_id | Task_name | Budget | ...
Or a table with user-IDs for assigned_to and assigned_from. All these tables can be joined together if you use 2nd Option.
btw it is the correct normalization form
You can use Option 2 and normalize further if tasks are always assigned by/from the same person.
Tasks table:
task_id | assigned_from
1 | 4
2 | 2
The Assignees table then doesn't need to have the assigned_from since it's always the same for that task_id:
id | task_id | assigned_to
1 | 1 | 1
2 | 1 | 3
3 | 1 | 6
4 | 2 | 1
5 | 2 | 4
i'm facing an issue when i'm trying to insert records in a table with similar columns. So basically my table is structured like this ::
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(50) | YES | MUL | NULL | |
+-------+-------------+------+-----+---------+----------------+
Now my PDO statement is this::
INSERT INTO supplement_brand (name) VALUES (:name)
So basically what i want is, that each name field will have a unique value. I already have INDEX set on the name field. Now i wanted to remove the primary key, and the auto-increment attributes from the id field. But that would entail bad database design practices.
Right now upon insertion the id field is being auto-incremented automatically, and many duplicate values are getting inserted in the name field:
Here is a sample of whats happening ::
+-----+-----------------------------+
| id | name |
+-----+-----------------------------+
| 1 | 2 to 1 Protein Bar |
| 7 | 2 to 1 Protein Bar |
| 8 | 2 to 1 Protein Bar |
| 28 | 2 to 1 Protein Bar |
| 93 | 2 to 1 Protein Bar |
| 98 | 2 to 1 Protein Bar |
| 230 | 2 to 1 Protein Bar |
| 231 | 2 to 1 Protein Bar |
| 232 | 2 to 1 Protein Bar |
| 2 | 360CUT |
| 3 | 360CUT |
| 4 | 360CUT |
| 5 | 360CUT |
| 6 | 360CUT |
| 9 | 4 Dimension Nutrition |
| 10 | 4 Dimension Nutrition |
| 11 | 4 Dimension Nutrition |
| 12 | 4 Dimension Nutrition |
| 13 | 4 Dimension Nutrition |
| 14 | 4 Dimension Nutrition |
| 15 | 4 Dimension Nutrition |
| 16 | 4 Dimension Nutrition |
| 17 | 4 Dimension Nutrition |
| 18 | 4 Dimension Nutrition |
| 19 | 4 Dimension Nutrition |
| 20 | 4 Dimension Nutrition |
| 21 | 4 Dimension Nutrition |
| 22 | 4 Dimension Nutrition |
| 23 | 4 Dimension Nutrition |
| 24 | 4 Dimension Nutrition |
| 25 | 4 Dimension Nutrition |
+-----+-----------------------------+
How can i prevent the insertion of duplicate values in the name field. Please provide any sort of help, i'm literally stuck right now. Thanks in advance
INDEX will not guarantee uniqueness. There is UNIQUE key created for such tasks.
ALTER TABLE `supplement_brand` ADD UNIQUE (`name`);
This should ensure that the name field requires a unique value.
If you add another column ie brand and you want the name to be unique, but only if they share the same brand also you can do the following:
ALTER TABLE `supplement_brand` ADD UNIQUE (`name` ,`brand`);
You have two option, first you can use UNIQUE for that field "name" statement above Or you can use UPSERT statements: follow this link for complete description: http://mechanics.flite.com/blog/2013/09/30/how-to-do-an-upsert-in-mysql/