Unique "Value" Issue with MySQL database - php

I am having a small and annoying issue with my MySQL database.
I have a field StudentID that is supposed to be unique for each user but is not mandatory.
So when the user registers and doesn't want to add a studentID - he leaves the field blank. However when a 2nd user leaves the field blank - it counts it as a duplicate value.
Is there any way to fix this ?I tried several methods posted below :
Mysql Error : 1062 - Duplicate entry '' for key
'users_studentid_unique'
1st time (works) :
insert into `users` (`username`, `name`, `email`, `studentid`,
`password`, `updated_at`, `created_at`)
values ('aaaaaa263', 'aaaaaa', 'aaaaaa23d#gmail.com','' ,
'yZPeKRV0C0xbr/QCI1w/Y.0Z1qSGnJeivgP71epaHpT139g65hAf2',
'2014-03-20 18:16:54', '2014-03-20 18:16:54')
2nd time (Duplicate value error for studentid) :
insert into `users` (`username`, `name`, `email`, `studentid`,
`password`, `updated_at`, `created_at`)
values ('aaaaaa263', 'aaaaaa', 'aaaaaa23d#gmail.com','' ,
'yZPeKRV0C0xbr/QCI1w/Y.0Z1qSGnJeivgP71epaHpT139g65hAf2',
'2014-03-20 18:16:54', '2014-03-20 18:16:54')
Tried :
Checking the NULL value on the studentid table in the database.
Tried inserting into the db using these values instead of the blank field :
NULL
null
UNDEFINED
Still having the same issue though, - Does anyone have any idea how to fix this problem?

Use a NULL value, that's not considered to be a "duplicate" in a unique index. But the column has to allow NULL values, that is, it cannot be defined as NOT NULL.
To insert a NULL value, use the keyword NULL keyword. Note that this is different than the character string 'NULL'
INSERT INTO mytab (a, b) VALUES (NULL, 'NULL')
Column a is assigned the special NULL value. Column b is assigned a character string.
Also, omitting the column from the INSERT list will cause the default value to be assigned to the column. The default value for a column is NULL, unless you've set the default to be something else.
This statement is equivalent to the statement above, in that column a will be assigned the default value defined for column a, which is
INSERT INTO mytab (b) VALUES ('NULL')
The other option is to use an expression to generate the NULL value for you, in the place of the empty string.
Given a description of your current logic, if the user_id column allows for NULL values, then you could translate the empty string to NULL
insert into `users` (`username`, `name`, `email`, `studentid`,
`password`, `updated_at`, `created_at`)
values ( ?, ?, ?, NULLIF( ? ,''), ?, ?, ?)
The NULLIF(x,y) function is shorthand for IF x = y THEN NULL ELSE x END.

You can set the student id to a timestamp if it's null, then check if its numeric to see if it's really set or not.
<?php
$student_id = is_null($student_id) ? time() : $student_id;
Your request :
insert into `users` (`username`, `name`, `email`, `studentid`,
`password`, `updated_at`, `created_at`)
values ('aaaaaa263', 'aaaaaa', 'aaaaaa23d#gmail.com','$student_id' ,
'yZPeKRV0C0xbr/QCI1w/Y.0Z1qSGnJeivgP71epaHpT139g65hAf2',
'2014-03-20 18:16:54', '2014-03-20 18:16:54')
Then to get the users back :
SELECT *, if(concat('','student_id' * 1) = 'student_id', 0, 1) as is_student_id_valid from ...
Then is_studient_id_valid field will tell you if this id is valid or not.

I have tried to recreate your problem. Alas, it works fine here.
However, i supply all the information so that you can at least check where your setup is different.
Create table statement: Please check all of: the Mysql Version, the table engine, the primary key and the index on the 'studentid' column.
/*
SQLyog Community v10.2
MySQL - 5.5.16 : Database - testmysql
*********************************************************************
*/
/*Table structure for table `users` */
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`username` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`studentid` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL,
`password` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`username`),
UNIQUE KEY `studentid_uidx` (`studentid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Typical insert with a null studentid...
INSERT INTO `users` (`username`, `name`, `email`, `studentid`,
`password`, `updated_at`, `created_at`)
VALUES ('aaaaaa004', 'aaaaaa', 'aaaaaa23d#gmail.com', NULL,
'yZPeKRV0C0xbr/QCI1w/Y.0Z1qSGnJeivgP71epaHpT139g65hAf2',
'2014-03-20 18:16:54', '2014-03-20 18:16:54')
query result
username name email studentid password created_at updated_at
aaaaaa001 aaaaaa aaaaaa23d#gmail.com (NULL) yZPeKRV0C0xbr/QCI1w/Y.0Z1qSGnJeivgP71epaHpT139g65hAf2 2014-03-20 18:16:54 2014-03-20 18:16:54
aaaaaa002 aaaaaa aaaaaa23d#gmail.com (NULL) yZPeKRV0C0xbr/QCI1w/Y.0Z1qSGnJeivgP71epaHpT139g65hAf2 2014-03-20 18:16:54 2014-03-20 18:16:54
aaaaaa003 aaaaaa aaaaaa23d#gmail.com stid01 yZPeKRV0C0xbr/QCI1w/Y.0Z1qSGnJeivgP71epaHpT139g65hAf2 2014-03-20 18:16:54 2014-03-20 18:16:54
aaaaaa004 aaaaaa aaaaaa23d#gmail.com (NULL) yZPeKRV0C0xbr/QCI1w/Y.0Z1qSGnJeivgP71epaHpT139g65hAf2 2014-03-20 18:16:54 2014-03-20 18:16:54

Related

error on local mysql but not on RDS mysql

I have a mysql insert query which runs on aws RDS(Live env) but throws an error on my local(local env).
on local I'am using mysql V-5.6
$sql = "INSERT INTO `users` (`id`,
`name`,
`email`,
`pass`)
values('','omi','omi#gmail.com','123123')
id is not null and auto_increment.
The error which i get on local is 'Incorrect integer value: '' for column 'id' at row 1'
but when this executed on live env all the data gets inserted into table.
I cant understand what exactly is happening here. please help. thank you.
DDL of users table.
local
CREATE TABLE `users`
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(256) DEFAULT '',
`email` varchar(256) NOT NULL,
`pass` varchar(256) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25986 DEFAULT CHARSET=utf8;
Live
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(254) DEFAULT '',
`email` varchar(256) NOT NULL,
`pass` varchar(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26046 DEFAULT CHARSET=utf8;
I believe the error is with those quotes (''). When you want to do an insert with an auto_increment field, you have to use null as argument in the auto_increment field position.
See if this works:
$sql = "INSERT INTO `users`
(`id`, `name`, `email`, `pass`)
values(null,'omi','omi#gmail.com','123123');
EDIT 1
Using null doesn't generate any error because internally the DBMS is prepared to receive such an argument. It understands that is its duty to generate the next number of the sequence and if it hasn't any, 0 (of type integer in your case) is inserted first. I know defining "not null" in the DDL of a field and then using "null" in the DML insert statement for that exact field may look confusing, but it's just the right way to use the auto_increment feature.
From the documentation:
If the column is declared NOT NULL, it is also possible to assign NULL to the column to generate sequence numbers.
Also, if using an empty string as argument in an statement doesn't generate any error, it could maybe be because RDS interface has an internal function that converts empty to null. Something like the nullif function in MySQL.
You can't do it like that. Either dont even mention 'id' or give it null value.
$sql = "INSERT INTO `users` (
`name`,
`email`,
`pass`)
values('omi','omi#gmail.com','123123')
OR:
$sql = "INSERT INTO `users` (`id`,
`name`,
`email`,
`pass`)
values('NULL','omi','omi#gmail.com','123123')

Mysql Create Table If Not Exists else.... Information Schema

Quick one hopefully - not sure where I'm going wrong here but this doesn't seem to work full stop.
Running MySQL query through PHP...
Current code
$uu = mysql_query("
IF EXISTS(SELECT table_name FROM information_schema.tables
WHERE table_schema = 'schema_example' AND table_name = 'test_q')
THEN
insert into `test_q` (code, va_desc, price, category)
values ('$code', '$desc', '$price', '$categ')
on duplicate key update va_desc='$desc', price='$price', category='$categ'
ELSE
CREATE TABLE `test_quote` (
`code` varchar(30) NOT NULL,
`va_desc` text NOT NULL,
`price` text NOT NULL,
`category` text NOT NULL,
PRIMARY KEY (`code`),
UNIQUE KEY `id` (`code`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
insert into `test_q` (code, va_desc, price, category)
values ('$code', '$desc', '$price', '$categ')
END IF;
")or die(mysql_error());
Really appreciate some help on what I need to change, at the moment this does absolutely nothing and doesn't return any specific errors. :/
Having said that if I run it in phpMyAdmin it returns the following (although I can't understand why):
#1064 - You have an error in your SQL syntax;
check the manual that corresponds to your MariaDB server
version for the right syntax to use near
'ELSE CREATE TABLE `test_quote`(
`code` varchar(30) NOT NULL,
`va_desc` text NO' at line 7
You don't need to query INFORMATION_SCHEMA. You can use the IF NOT EXISTS option to CREATE TABLE.
mysql_query("CREATE TABLE IF NOT EXISTS `test_q` (
`code` varchar(30) NOT NULL,
`va_desc` text NOT NULL,
`price` text NOT NULL,
`category` text NOT NULL,
PRIMARY KEY (`code`),
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1");
mysql_query("insert into `test_q` (code, va_desc, price, category)
values ('$code', '$desc', '$price', '$categ')
on duplicate key update va_desc='$desc', price='$price', category='$categ'");
Also, a primary key is a unique key, you don't need to specify them both when you create the table.
Trying using the following query as if, else and then statements are not supported in the sql query, for that you can stored procedures.
mysql_query("CREATE TABLE IF NOT EXISTS `test_q` (`code` varchar(30) NOT NULL,
`va_desc` text NOT NULL,
`price` text NOT NULL,
`category` text NOT NULL,
PRIMARY KEY (`code`),
);
mysql_query("insert into `test_q` (code, va_desc, price, category)
values ('$code', '$desc', '$price', '$categ')
on duplicate key update va_desc='$desc', price='$price', category='$categ'");

php get the row from serialize data where condition is satisfied

In mysql I have the table look like this
CREATE TABLE IF NOT EXISTS `fl_details` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`email` varchar(100) NOT NULL,
`phone` varchar(15) NOT NULL,
`country` varchar(100) NOT NULL,
`language_pair` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
and the values inside table is like this. I have jut shown two entries. But there are more then 100 row present.
INSERT INTO `fl_details` (`id`, `first_name`, `last_name`, `email`, `phone`, `country`, `language_pair`) VALUES
(1, 'asdf', 'erty', 'testuser#gmail.com', '12345678909', 'Sri Lanka', 'a:2:{s:6:"source";a:2:{i:0;a:1:{i:0;s:6:"Arabic";}i:1;a:1:{i:0;s:10:"Belarusian";}}s:6:"target";a:2:{i:0;a:2:{i:0;s:8:"Assamese";i:1;s:11:"Azerbaijani";}i:1;a:2:{i:0;s:10:"Belarusian";i:1;s:7:"Bengali";}}}'),
(2, 'asth', 'erui', 'testname#gmail.com', '12312356789', 'India', 'a:2:{s:6:"source";a:1:{i:0;a:1:{i:0;s:7:"English";}}s:6:"target";a:1:{i:0;s:5:"English";}}');
Here you can see I have entered the values for language_pair is in php serialize format. So both source and target language is stored in that column.
Now I want to fetch the total row whose target language is Bengali. So can someone kindly tell me how to do this? Any help and suggestions will be really appreacible. Thanks
you can try something like this
SELECT * FROM fl_details WHERE language_pair REGEXP '.*"target";s:[0-9]+:"English".*'

How to check if column 1 has two different values for column 2

I am trying to make a INSERT by UNIQUE and I am getting stuck, What I want too know is how I would do is make it so Column A is ALWAYS UNIQUE unless Column C has two different values and then it will insert into the database a second row for Column A where Column C is different.
a|b|c
-----
1|2|3
2|4|5
1|6|7
So I am currently using this sql table
CREATE TABLE `Player` (
`id` int(11) NOT NULL auto_increment,
`playername` varchar(255) NOT NULL,
`SteamID` varchar(255) NOT NULL UNIQUE,
`position` varchar(255) NOT NULL,
`lastlogin` varchar(255) NOT NULL,
`approved` varchar(255) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
With this query
$sql1= "INSERT IGNORE INTO Player (playername, SteamID, position, lastlogin, approved) VALUES ('$name', '$id', '$position', '$lastlogin', '$approve')";
It inserts the way I want so there is only 1 of each SteamID but it also will not insert if the same SteamID has two values for position.
EDIT:
What I have is a xml file I load up and insert data into the database based on the data in the xml file, What I need is below.
$xml = simplexml_load_file("players.xml");
foreach($xml->children() as $player)
{
$id = $player->attributes()->id;
$profile = new SteamProfile($id);
$name = mysql_real_escape_string($profile->getUsername());
$lastlogin = $player->attributes()->lastlogin;
$position = $player->lpblock->attributes()->pos;
$sql1= "INSERT IGNORE INTO Player (playername, SteamID, position, lastlogin, approved) VALUES ('$name', '$id', '$position', '$lastlogin', '$approve')";
if (!mysql_query($sql1,$connection))
{
die('Insert Error: ' . mysql_error());
}
}
so the xml file gets read and then the data in the file gets inserted into the database. sometimes the xml file would contain
<player id="76561197961716203" lastlogin="8/22/2014 10:49:28 PM">
<acl id="76561197961543041"/>
<acl id="76561197988417990"/>
<lpblock pos="273,93,-102"/>
<lpblock pos="1322,62,-1711"/>
</player>
at which point I would need a second row created for the second <lpblock pos=
So its currently inserting
|60|SwordFish |76561197961716203|273,93,-102|8/22/2014 10:49:28 PM|Yes|2014-08-24 15:28:16|
and it should be inserting
|60|SwordFish |76561197961716203|273,93,-102|8/22/2014 10:49:28 PM|Yes|2014-08-24 15:28:16|
|61|SwordFish |76561197961716203|1322,62,-1711|8/22/2014 10:49:28 PM|Yes|2014-08-24 15:28:16|
I'm not sure what you are trying to achieve, but you can set a UNIQUE restraint on a combination of columns, in your case SteamID and position:
CREATE TABLE `Player` (
`id` int(11) NOT NULL auto_increment,
`playername` varchar(255) NOT NULL,
`SteamID` varchar(255) NOT NULL,
`position` varchar(255) NOT NULL,
`lastlogin` varchar(255) NOT NULL,
`approved` varchar(255) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_combination_of_two_fields` (`SteamID`,`position`)
) ENGINE=InnoDB;
Thanks for you help Jeroen I did this and its working.
foreach($player->children() as $lpblock)
{
$position = $lpblock->attributes()->pos;
if(!empty($position))
{
$sql1= "INSERT IGNORE INTO Player (playername, SteamID, position, lastlogin, approved) VALUES ('$name', '$id', '$position', '$lastlogin', '$approve')";
if (!mysql_query($sql1,$connection))
{
die('Insert Error: ' . mysql_error());
}
}
}
However I would like all of the SteamID's inserted and not just the ones with a $position set. When I take this out and try it adds the correct rows but also adds another row with a blank $position as if there is a SteamID that's blank when there is none.
if(!empty($position)){
}

Need to insert SQL without duplicates

The table is currently this:
CREATE TABLE `feed_items` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`feed_id` int(11) NOT NULL,
`remote_id` varchar(32) NOT NULL DEFAULT '',
`title` varchar(255) NOT NULL DEFAULT '',
`link` varchar(255) NOT NULL DEFAULT '',
`updated_time` datetime NOT NULL,
`created_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
I need to find a way so that if i pull multiple RSS feeds into one table, and articles with the same Title have the same value of 'remote_id', how can i make sure I do not insert a duplicate value?
I am currently using
$this->db->query('INSERT INTO feed_items(feed_id, remote_id, link, title, created_time, updated_time) VALUES (?, ?, ?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE remote_id=remote_id', array($this->feed_id, $this->remote_id, $this->link, $this->title, $this->created_time, $this->remote_id));
I was wondering if there is a better way?
Add a UNIQUE constraint to those two columns.
ALTER TABLE `feed_items` ADD UNIQUE INDEX `constraint` (`link`, `remote_id`);
You can use ON DUPLICATE for avoiding such conditions: Check: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
Hope it helps
Try this:
$this->db->query('INSERT INTO feed_items(feed_id, remote_id, link, title, created_time, updated_time) SELECT ?, ?, ?, ?, ?, NOW() WHERE not exists(SELECT 1 FROM feed_items f2 WHERE f2.title = ? and f2.remote_id = ?)', array($this->feed_id, $this->remote_id, $this->link, $this->title, $this->created_time, $this->title, $this->remote_id));
Just to clarify - this solution changes the insert into ... values statement to an insert into...select statement, with a not exists() clause attached. This not exists clause will prevent the insert from doing anything if it finds a record that matches one that is already present. It won't throw an error if there is a pre-existing record.
Thanks for the replies!
I actually managed to solve it a few hours after posting this, I made the remote_id a unique column and then did the following for the SQL
INSERT INTO feed_items(feed_id, remote_id, link, title, created_time, updated_time) VALUES (?, ?, ?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE remote_id=remote_id

Categories