How do I make my sql Primary Key automaticlly count up? - php

I defined the column id as my primary key, but how do I make it automatically one larger than the last one?

You are lookin for AUTO_INCREMENT, you can check documentation here
You will need to set id column as AUTO_INCREMENT
Example from documentation
CREATE TABLE animals (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM;

you must set autoincrement.
CREATE TABLE animals (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM;
INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');
SELECT * FROM animals;
Which returns:
+----+---------+
| id | name |
+----+---------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | whale |
| 6 | ostrich |
+----+---------+
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html mysql reference

Ok didn't notice the tags.
Hit the A_I checkbox in phpMyAdmin for the id column.
---old---
The Oracle way, triggered sequence:
CREATE sequence aic increment BY 1 start WITH 1;
CREATE TABLE blarg (
id NUMBER(15,0) PRIMARY KEY,
foobar VARCHAR2(255)
);
CREATE TRIGGER trigger ait BEFORE INSERT ON blarg
REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW
Begin
SELECT aic.NEXTVAL INTO :NEW.id FROM DUAL;
End;

Related

Confusion between PK and FK table design

I have a person table and a score table. The Person table basically stores a person's information while score table stores what kind of score a person has. I set the FK constraint in score table to ON DELETE: CASCADE
person
- id
- name
- scored_id (FK)
score
- id (PK)
- bmi
- weight
So, in the table setting score.id is linked with person's scored_id. That being said when I delete a record in score, a person will get deleted as well. But why when I delete a record in person, the record of his in score is not deleted?
Just an idea how you might structure the tables and use a foreign key which will delete records from the score table if/when a user from the person table is deleted. The score table should have a reference to the user - pid which is used as the foreign key dependancy. It makes sense to me that the score is dependant upon the user so no user, no score.
create table `person` (
`id` int(10) unsigned not null auto_increment,
`name` varchar(50) null default null,
primary key (`id`)
)
collate='latin1_swedish_ci'
engine=innodb
auto_increment=4;
mysql> describe person;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(50) | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
create table `score` (
`id` int(10) unsigned not null auto_increment,
`bmi` int(10) unsigned not null default '0',
`weight` int(10) unsigned not null default '0',
`pid` int(10) unsigned not null default '0',
primary key (`id`),
index `pid` (`pid`),
constraint `fk_sc_pid` foreign key (`pid`) references `person` (`id`) on update cascade on delete cascade
)
collate='latin1_swedish_ci'
engine=innodb
auto_increment=4;
mysql> describe score;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| bmi | int(10) unsigned | NO | | 0 | |
| weight | int(10) unsigned | NO | | 0 | |
| pid | int(10) unsigned | NO | MUL | 0 | |
+--------+------------------+------+-----+---------+----------------+
mysql> select * from person;
+----+------+
| id | name |
+----+------+
| 1 | bob |
| 2 | rita |
| 3 | sue |
+----+------+
mysql> select * from score;
+----+-----+--------+-----+
| id | bmi | weight | pid |
+----+-----+--------+-----+
| 1 | 34 | 34 | 1 |
| 2 | 56 | 41 | 2 |
| 3 | 56 | 77 | 3 |
+----+-----+--------+-----+
mysql> delete from person where id=3;
Query OK, 1 row affected (0.00 sec)
/* delete a user, the score disappears too which makes sense */
mysql> select * from score;
+----+-----+--------+-----+
| id | bmi | weight | pid |
+----+-----+--------+-----+
| 1 | 34 | 34 | 1 |
| 2 | 56 | 41 | 2 |
+----+-----+--------+-----+
Your issue is semantic understanding of the task, rather than syntax. Intuitively your relation looks wrong. It is unlikely, that a particular score, say 75kg and bmi of 20 will need to have a many relations link to people with the same score. This would be arbitary. More likely, your want, a person to have different scores over time, then when you delete a person, you want their associated values deleted. So table relation should be:
person
- id (Primary Key)
- name
score
- id (Primary Key)
- bmi
- weight
- scoreDate
- personID (Foreign Key to person)
A score date would be a helpful addition.
This structure will allow a person to have a history of many score and see the fluctuation of their weight and body mass index over time. A semantically helpful task that resonates with reality, and therefore follows the notions of entity analysis and table structures following the real world application.
Helpful discussion of ERD and table structure levels and relations
In you tables, "person" table is having reference(FK) of "score" table so when you delete a record in "score" table mysql search related record in "users" table to delete.
but "score" table dose not have any reference(FK) of "person" table.
You can try below table structure if you want to delete score record when person record will be delete but person record will be still safe if score record will be delete
person
- id (PK)
- name
score
- id (PK)
- person_id (FK)
- bmi
- weight

Generating Sequencial ID with Suffix and Prefix in php [duplicate]

I have table like this
table
id Varchar(45) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name CHAR(30) NOT NULL,
I want to increment my id field like 'LHPL001','LHPL002','LHPL003'... etc.
What should I have to do for that? Please let me know any possible way.
If you really need this you can achieve your goal with help of separate table for sequencing (if you don't mind) and a trigger.
Tables
CREATE TABLE table1_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE table1
(
id VARCHAR(7) NOT NULL PRIMARY KEY DEFAULT '0', name VARCHAR(30)
);
Now the trigger
DELIMITER $$
CREATE TRIGGER tg_table1_insert
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO table1_seq VALUES (NULL);
SET NEW.id = CONCAT('LHPL', LPAD(LAST_INSERT_ID(), 3, '0'));
END$$
DELIMITER ;
Then you just insert rows to table1
INSERT INTO Table1 (name)
VALUES ('Jhon'), ('Mark');
And you'll have
| ID | NAME |
------------------
| LHPL001 | Jhon |
| LHPL002 | Mark |
Here is SQLFiddle demo
Create a table with a normal numeric auto_increment ID, but either define it with ZEROFILL, or use LPAD to add zeroes when selecting. Then CONCAT the values to get your intended behavior. Example #1:
create table so (
id int(3) unsigned zerofill not null auto_increment primary key,
name varchar(30) not null
);
insert into so set name = 'John';
insert into so set name = 'Mark';
select concat('LHPL', id) as id, name from so;
+---------+------+
| id | name |
+---------+------+
| LHPL001 | John |
| LHPL002 | Mark |
+---------+------+
Example #2:
create table so (
id int unsigned not null auto_increment primary key,
name varchar(30) not null
);
insert into so set name = 'John';
insert into so set name = 'Mark';
select concat('LHPL', LPAD(id, 3, 0)) as id, name from so;
+---------+------+
| id | name |
+---------+------+
| LHPL001 | John |
| LHPL002 | Mark |
+---------+------+
I know it is late but I just want to share on what I have done for this. I'm not allowed to add another table or trigger so I need to generate it in a single query upon insert. For your case, can you try this query.
CREATE TABLE YOURTABLE(
IDNUMBER VARCHAR(7) NOT NULL PRIMARY KEY,
ENAME VARCHAR(30) not null
);
Perform a select and use this select query and save to the parameter #IDNUMBER
(SELECT IFNULL
(CONCAT('LHPL',LPAD(
(SUBSTRING_INDEX
(MAX(`IDNUMBER`), 'LHPL',-1) + 1), 5, '0')), 'LHPL001')
AS 'IDNUMBER' FROM YOURTABLE ORDER BY `IDNUMBER` ASC)
And then Insert query will be :
INSERT INTO YOURTABLE(IDNUMBER, ENAME) VALUES
(#IDNUMBER, 'EMPLOYEE NAME');
The result will be the same as the other answer but the difference is, you will not need to create another table or trigger. I hope that I can help someone that have a same case as mine.
Here is PostgreSQL example without trigger if someone need it on PostgreSQL:
CREATE SEQUENCE messages_seq;
CREATE TABLE IF NOT EXISTS messages (
id CHAR(20) NOT NULL DEFAULT ('message_' || nextval('messages_seq')),
name CHAR(30) NOT NULL,
);
ALTER SEQUENCE messages_seq OWNED BY messages.id;

How to update a row with multiple images which has only single image inserted initially in php

I have a table with columns id,image and organisation name.I have inserted single image for each organisation initially but i need to update it with multiple images for each organisation.I am using php ver 5.4.16 and mysql ver 5.6.12.
Try to use a separator, for example use comma and store it like this in your table :
id image organization
1 path_to/img1.png org_name1
2 path_to/img1.png,path_to/img2.png org_name2
and later, after you extract the record, use explode function to extract it to an array like this :
$images = explode(",", $data->image);
PS : please give enough length for the image field, for example, give it varchar(4000), this is to make sure there will be no string truncation
Split the table in two and use the id of your table as foreign key in the new image table. ("normalization" and "relations" should be your search tags) https://en.wikipedia.org/wiki/Database_normalization
Or if you can't you should use json to insert multiple content. http://php.net/manual/en/book.json.php
You need to add a new table named "image" with columns :
- id_img
- image
- ref_organisation_id (foreign_key)
The best solution, in my opinion, to your problem would be to slightly redesign your database schema - the existing table will not be able to store multiple images for the same company judging by the overview of the tables you gave in the question.
There ought to be a table for orgainisations and another table for images associated with those organisations. The images table would have a key that links to the organisations table.
A very quickly put together example database structure
+----+------------------+
| id | name |
+----+------------------+
| 1 | ACME Web Company |
| 2 | ACME ISP |
+----+------------------+
+----+--------+------------+
| id | org_id | image |
+----+--------+------------+
| 1 | 1 | logo.jpg |
| 2 | 1 | banner.jpg |
| 3 | 1 | badge.png |
| 4 | 2 | logo.jpg |
| 5 | 2 | banner.gif |
+----+--------+------------+
create table if not exists `organisations` (
`id` int(10) unsigned not null auto_increment,
`name` varchar(50) not null,
primary key (`id`)
) engine=innodb auto_increment=3 default charset=utf8;
insert into `organisations` (`id`, `name`) values
(1, 'acme web company'),
(2, 'acme isp');
create table if not exists `org_images` (
`id` int(10) unsigned not null auto_increment,
`org_id` int(10) unsigned not null,
`image` varchar(50) not null,
primary key (`id`),
key `org_id` (`org_id`),
constraint `fk_org` foreign key (`org_id`) references `organisations` (`id`) on delete cascade on update cascade
) engine=innodb auto_increment=6 default charset=utf8;
insert into `org_images` (`id`, `org_id`, `image`) values
(1, 1, 'logo.jpg'),
(2, 1, 'banner.jpg'),
(3, 1, 'badge.png'),
(4, 2, 'logo.jpg'),
(5, 2, 'banner.gif');

How to remove multi-level menu item with children in MySQL?

I have unlimited level menu structure in MySQL, where parent and children elements are connected with column p_id:
+----+------+------+----------------+
| id | p_id | sort | name_en |
+----+------+------+----------------+
| 1 | 0 | 1 | menu-1 |
| 2 | 0 | 2 | menu-2 |
| 3 | 0 | 6 | menu-3 |
| 4 | 2 | 3 | sub-menu-2-1 |
| 5 | 2 | 4 | sub-menu-2-2 |
| 6 | 5 | 5 | sub-menu-2-2-1 |
+----+------+------+----------------|
What is best practice for deleting root menu element with sub-menu elements?
I can achieve it with PHP recursion, but it will cause some number of queries.
So I need to find out if is there any possible way to do it with one MySQL query.
Since you have name_en, cannot you use that one to delete the rows? For example,
DELETE FROM `table` WHERE `id` = 2 OR `name_en` LIKE 'sub-menu-2-%'
New method:
You can use a Foreign Key with a constraint. I created your table and called it treelist,
CREATE TABLE `treelist` (
`item_id` int(10) unsigned NOT NULL auto_increment,
`parent_id` int(10) unsigned default NULL,
`name_en` varchar(40) NOT NULL,
PRIMARY KEY (`item_id`),
KEY `FK_parent_id` (`parent_id`),
CONSTRAINT `FK_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `treelist` (`item_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I then added some test data, the ones you had in your question,
INSERT INTO `treelist` (`item_id`, `parent_id`, `name_en`) VALUES (NULL, NULL, 'Menu 1'), (NULL, NULL, 'Menu 2'), (NULL, NULL, 'Menu 3'), (NULL, 2, 'Sub Menu 2-1'), (NULL, 2, 'Sub Menu 2-2'), (NULL, 5, 'Sub Menu 2-2-1');
Now, when you delete a row, for example
DELETE FROM `treelist` WHERE `item_id` = 2
It will delete all children, grand-children etc as well. Afterwards the table looks like,
+----+------+----------------+
| id | p_id | name_en |
+----+------+----------------+
| 1 | NULL | Menu 1 |
| 3 | NULL | Menu 3 |
+----+------+----------------+
To delete just a row and it's direct children (not grandchildren):
DELETE FROM tablename where id = 1 or p_id = 1;
UPDATE 1:
If you have freedom to add a column to the table, you could add root_id and easily do the delete based on that. This will not ruin any current queries in your system and will only take a one-time run of a simple script to add the initial data.
DELETE FROM tablename where id = 1 or root_id = 1;
UPDATE 2:
A pretty awesome option is that foreign keys to the same table are allowed. So you can add a foreign key to p_id that references id, use on delete cascade and when you delete the root, all descendants will be removed also. I created a test table and this worked beautifully for me. It may also be beneficial to add on update cascade. Remember that p_id as well as id need to be unsigned for this to work.
ALTER TABLE tablename ADD CONSTRAINT fk_tablename_id FOREIGN KEY (p_id) references tablename(id) ON DELETE CASCADE;
Just category id or parent id in first parameter:
function delete_parent_and_child_subchild($category_id,$all_cate=array())
{
if(!is_array($category_id))
{
$this->db->where('parent_id', $category_id);
$all_cate[]=$category_id;
}
else
{
$this->db->where_in('parent_id', $category_id);
}
$get_categories= $this->db->get('newcategory');
if($get_categories->num_rows()>0)
{
$categories_vales=$get_categories->result();
$new_subcat = array();
foreach($categories_vales as $cate_val)
{
$category_id=$cate_val->category_id;
array_push($new_subcat,$category_id);
}
$all_cate = array_merge($all_cate,$new_subcat);
if(count($new_subcat)>0)
{
$this->delete_parent_and_child_subchild($new_subcat,$all_cate);
}
}
$this->db->where_in('category_id', $all_cate)->delete('newcategory');
return true;
}

MySQL question: How to insert unique non-integer employee ids?

I want to insert data into a table like the following:
emp_id emp_data
----------------------------
emp001 Amit
emp002 Ajit
emp003 Arijit
Over here all the emp_id data should be unique but should follow the pattern of emp***. Please help. I am a novice in db.
create table employee (
empnum varchar(10) primary key
, empname varchar(60)
);
insert into employee values ('emp001', 'Employee 1');
insert into employee values ('emp002', 'Employee 2');
insert into employee values ('100emp', 'Employee 3');
once i asked similar question, but later i realized that , this is not good idea to add prefix/suffix with auto increment field
better u change your table structure
emp_id emp_uniq_id emp_data
----------------------------------
1 emp001 Amit
2 emp002 Ajit
3 emp003 Arijit
and u can use below query
mysql_query("UPDATE table_name SET emp_uniq_id=CONCAT('emp', ".str_pad(emp_id,3,'0',STR_PAD_LEFT).") )";
If the emp prefix is going to remain constant it makes more sense to store it your application logic and prepending it when fetching columns from the database.
Either way, you're only going to be able to AUTO_INCREMENT numeric columns.
That having been said, you can group your primary key like so:
CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
The output of the select would be:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
Cribbed from the online docs: http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html

Categories