I'm trying to test how the insert into duplicate key works. And currently this is what I did:
INSERT INTO
user_test (userName, first, last)
SELECT
u.userName, u.first, u.last
FROM otherdatabase.user as u
ORDER BY u.userName ASC
ON DUPLICATE KEY UPDATE
userName = u.userName
I executed this query and it worked and inserted rows. Then what I did was I modified one row from the user table and then tried to run this query again, but instead of just updating that one row it inserted all the rows again.
From what I understand shouldn't it just update that one row I modified from the user table?
What I'm trying to do is do a "Insert if it doesn't exist and update if it exist" query and found that using insert into .. on duplicate key can do that but I'm obviously doing it wrong...
CREATE TABLE user_test (
id bigint(20) NOT NULL AUTO_INCREMENT,
userName varchar(20) DEFAULT NULL,
first varchar(20) DEFAULT NULL,
last varchar(20) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=64 DEFAULT CHARSET=latin1
Per Barranka's suggestion I added a unique index to the user_name column
Alter table user_test add unique index idx_userName(userName)
Then I ran the query again and it didn't add any more rows since its already existing..
This is an example of what the user_table looks like now, its now the same on the users table.
user_table:
userName | first | last |
ckeith | Carl | Keith |
mmonroe | Mickey | Monroe |
Then what I did to test it again is from the user table I modified one of the rows
user:
userName | first | last |
ckeithh | Carl | Keith |
mmonroe | Mickey | Monroe |
and executed the query again, this is now what the users_table looks like:
user_table:
userName | first | last |
ckeith | Carl | Keith |
mmonroe | Mickey | Monroe |
ckeithh | Carl | Keith |
I thought it would just update the first row to ckeithh but it just inserted one row?
My expected output was:
user_table:
userName | first | last |
ckeithh | Carl | Keith |
mmonroe | Mickey | Monroe |
Update:
I added a unique index and made sure that it is unique. The inserting works but now the update is not working. Anything else i should try?
Still not able to get this to work, I have confirmed that the column i'm using is unique and that my version of mysql is v5 (i saw on one of the forums that for this to work mysql should be v5, not sure if thats real or not, but still i checked and im using v5.5.37)
Related
I would like to enter two of the same emails as two different rows into MySQL table Person. However, it keeps only one row. How do I modify my code? Thanks.
create table if not exists Person (
Id int auto_increment primary key,
Email varchar(20)
);
insert into Person(Email)
values ('abc#efg.com'),
('abc#efg.com')
;
Your query looks ok
SQL fiddle demo
OUTPUT
| Id | Email |
|----|-------------|
| 1 | abc#efg.com |
| 2 | abc#efg.com |
I'm trying like hours to make a simple MySQL command and it won't work.
I have a database where package IDs for Apps are stored, like 'com.android.package'.
They are stored like so:
| ID | PackageID | PackageDesc |
| 1 | com.android.package | This is a package |
| 2 | com.android.test2pa | This is package 2 |
And so on...
Now I want to insert a new entry, if 'com.android.package' don't exist and if it exists, I want to do nothing...
I've tried following:
INSERT INTO Packages (PackageID) VALUES ('com.android.package') ON DUPLICATE KEY UPDATE PackageID=VALUES(PackageID)
But it still creates new entries, like that:
| ID | PackageID | PackageDesc |
| 3 | com.android.package | |
| 4 | com.android.package | |
| 5 | com.android.package | |
I don't know where's my error.
A proposed Packages table schema for ON DUPLICATE KEY UPDATE to work as expected is the following:
CREATE TABLE Packages (
`ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`PackageID` VARCHAR(30) NOT NULL,
`PackageDesc` VARCHAR (100),
UNIQUE(`PackageID`)
);
After this statement is executed:
INSERT INTO Packages (PackageID, PackageDesc) VALUES
('com.android.package', 'This is a package')
ON DUPLICATE KEY UPDATE PackageID=VALUES(PackageID);
Packages contains the following row:
# ID, PackageID, PackageDesc
'1', 'com.android.package', 'This is a package'
If you now execute the following statement:
INSERT INTO Packages (PackageID, PackageDesc) VALUES
('com.android.package', 'This is a package2')
ON DUPLICATE KEY UPDATE PackageID=VALUES(PackageID), PackageDesc=VALUES(PackageDesc);
Packages contains:
# ID, PackageID, PackageDesc
'1', 'com.android.package', 'This is a package2'
This means an UPDATE was performed by the latter INSERT INTO.
Demo here
The task is to fill the table with N rows of random unique data.
I have the next MySQL table structure:
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(20) | NO | UNI | NULL | |
+----------+--------------+------+-----+---------+----------------+
Username field has string type but if the script will insert numbers its OK.
Theres is dirty solution with INSERT IGNORE, that can make 1000 random rows with endless cycle.
INSERT IGNORE INTO table (id,username) VALUES ('', 1 + ceil(rand() * 1000));
Also, I can use ON DUPLICATE KEY structure, but this 2 solutions are not OK.
I want to make the query, that generate unique username which will be unique and will be inserted from the first time.
So, I tell the script to add 1m of rows and it will insert 1m of unique data without any infelicities.
Any ideas? Thanks.
You can use UUID() which will give you a random string which would fit in your field, guaranteed to be unique with slim chance of collisions.
I have a query that supposed to display a page's name where a particular user has accessed to. The users table has a column that has a CSV of page ids that the user has accessed to.
The page's names is located in another table with corresponding page ids.
Here is the structure of the 2 tables
+------------+---------------------+
| User Table | |
+------------+---------------------+
| USERID | PAGE |
| john01 | 101,102, |
| chris5 | 101,001,003,004,005 |
+------------+---------------------+
+------------+------------------+
| PAGE TABLE | |
+------------+------------------+
| PAGEID | PAGENAME |
| 101 | Account settings |
| 102 | Details |
| 001 | Setup account |
| 002 | Profile |
| 003 | Reset Password |
| 004 | Edit user |
| 005 | Manage accounts |
+------------+------------------+
My problem is how can I display all page names accessible to a particular user like:
john01
My query is:
select pagename as Pages
from
Page
where
pageid in (select page from user where userid = 'john01')
This query only displays one pagename but not 2 pagenames as indicated on the table structure.
How can I retreive all pages for a particular user using this 2 table structure?
Thanks in advance.
This is not the best structure to go, but I believe you can manage it using this query:
( I would however strongly recommend to normalize the user page table to make a single page id per record reference.)
SELECT p.pagename FROM Pages p, User u WHERE u.userid = "john01" AND u.PAGE LIKE "%p.PAGEID%"
EDIT:
I started PhpMyAdmin to recreate the query, however since I believe it's not in my nature to write a query like this.
I would recommend you to normalize your table structure like this:
CREATE TABLE IF NOT EXISTSpage(
idint(10) unsigned NOT NULL AUTO_INCREMENT,
namevarchar(25) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
CREATE TABLE IF NOT EXISTSuser(
idint(10) unsigned NOT NULL AUTO_INCREMENT,
namevarchar(25) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTSuserpages(
useridint(10) unsigned NOT NULL,
pageidint(10) unsigned NOT NULL,
PRIMARY KEY (userid,pageid)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Now the page table lists all available pages. the user table just list usernames to user id's. and the magic happens in the userpages table. where you make relevant references (rights?) between pages and users.
You can now query the pages using the following SQL query:
SELECT p.id, p.name FROM page p, user u, userpages up WHERE u.name = 'john01' and u.id = up.userid AND up.pageid = p.id
It may sound similar but,I am working on partitioning on some table...the table looks like
mysql> DESC SHOPS;
+-------------------+-------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-------------+------+-----+-------------------+-----------------------------+
| SHOP_ID | int(255) | NO | PRI | NULL | |
| SHOP_NAME | varchar(50) | YES | | NULL | |
| SHOP_CREATED_DATE | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------------------+-------------+------+-----+-------------------+-----------------------------+
3 rows in set (0.00 sec)
so i have search feature where people can search only by shop name so table have around 1 million records so i wanted to RANGE partitioning on shop name alphabetically but i cant do since i have primary key shop_id and shop name can be same...and getting error
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the
table's partitioning function
Solution:
ALTER TABLE SHOPS ADD CONSTRAINT T UNIQUE (SHOP_ID,SHOP_NAME);
And do partitioning ...i cant do this because it does not make sure shop_id is unique(Primary Key)
You can, and you must. Assuming you always let AUTO_INCREMENT do its thing, shop_id will always be unique, and any index starting with shop_id is all you need.
int(255) -- The (255) means nothing. An INT (SIGNED, by default) has a range of -2 billion to +2 billion and occupies 4 bytes, regardless of the (...) after it..
There is probably no performance advantage (or any other advantage) of Partitioning this table. If you think otherwise, please show us a query that you think will benefit.
Please use SHOW CREATE TABLE; it is more descriptive than DESCRIBE.