I'm working on a MySQL database for shop items. I want these shop items to have IDs like 0001, 0002 etc. But if I use AUTO_INCREMENT (which I need) it will go as 1, 2 etc. Is there any way to make AUTO_INCREMENT for PRIMARY KEY work this way because I need IDs to have a specific number of characters?
This is the code where I'm creating the items table:
CREATE TABLE items (
item_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(30) NOT NULL,
price FLOAT NOT NULL,
discount INT
);
This is the Python loop where I'm putting all items from .csv file into the database table:
for item in items_list:
mycursor.execute(f"INSERT INTO items(name, price, discount) VALUES ({item['name']}, {item['price']}, {item['discount']});")
Is it possible to make AUTO_INCREMENT work that way or I need to do it manually?
Primary keys need to have one job only, that of uniquely identifying a row. As soon as you start trying to make them look presentable by formatting them or make them sequential without gaps, or even when you try to use them to see if one row was created before another, you create reasons to want to change them.
Practically anything visible to users or involved in business logic is going to end up needing to change. And primary keys shouldn't change. Changing a primary key means deleting the row and making a new one with the new key value, and also fixing all the references to the old key. It's fiddly and tedious and error-prone, it is something you want to avoid.
Make a separate column for a user-visible identifier separate from the PK that you can have full control over. You can populate it with a trigger or application code based off the key if you want. Just keep it separate from the primary key.
Auto_incrememts are tricky, because they can't be used in BEFORE INSERT TRIGGER it is alays 0
so you need another table and a AFTER INSERT TRIIGGER
CREATE TABLE items (
item_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(30) NOT NULL,
price DECIMAL(10,2) NOT NULL,
discount INT
);
CREATE TABLE t1 (
item_id_1 varchar(8) )
CREATE TRIGGER ins_sum AFTER INSERT ON items
FOR EACH ROW INSERT INTO t1 VALUES(LPAD (NEW.item_id , 8, '0'));
INSERT INTO items (name,price, discount) VALUES ('test1',1.1,1)
INSERT INTO items (name,price, discount) VALUES ('test2',1.1,1)
INSERT INTO items (name,price, disc
SELECT * FROM t1
| item_id_1 |
| :-------- |
| 00000001 |
| 00000002 |
| 00000003 |
SELECT *,(SELECT item_id_1 FROM t1 WHERE item_id_1 + 0 = i.item_id) FROM items i
item_id | name | price | discount | (SELECT item_id_1 FROM t1 WHERE item_id_1 + 0 = i.item_id)
------: | :---- | ----: | -------: | :---------------------------------------------------------
1 | test1 | 1.10 | 1 | 00000001
2 | test2 | 1.10 | 1 | 00000002
3 | test3 | 1.10 | 1 | 00000003
SELECT i.*,t1.item_id_1 FROM items i JOIN t1 ON i.item_id = t1.item_id_1 + 0
item_id | name | price | discount | item_id_1
------: | :---- | ----: | -------: | :--------
1 | test1 | 1.10 | 1 | 00000001
2 | test2 | 1.10 | 1 | 00000002
3 | test3 | 1.10 | 1 | 00000003
db<>fiddle here
Related
create table Branch
(
BranchNo char(4),
Street varchar(30),
City varchar(30),
PostCode varchar(10)
)
INSERT INTO BRANCH
VALUES ('B002', '55 cOVER', 'LONDON',NULL)
INSERT INTO BRANCH
VALUES ('B003', '163 Main Street', 'Glasgow',NULL)
INSERT INTO BRANCH
VALUES ('B004', '32 Manse Road', 'Bristol',NULL)
INSERT INTO BRANCH
VALUES ('B005', '22 Dear Road', 'LONDON',NULL)
INSERT INTO BRANCH
VALUES ('B007', '16 Argyll', 'Abend',NULL)
Create a view named ViewDeC that displays information of all branches. Must say
make sure it is not possible to update the data for the branch table (Branch) through this View
Create a view and don't let the database update mysql?
enter image description here
If I am not mistaken, this is about how to create a readonly view. Though MySQL does not support creating a view with readonly attribute DIRECTLY, certain things can be done to make the view READONLY. One workaround is to make the view through joined tables.
create view ViewDeC as
select BranchNo,Street,City,PostCode
from Branch
join (select 1) t;
select * from ViewDec;
INSERT INTO ViewDec
VALUES ('B009', '99 Argyll', 'bender',NULL);
-- Error Code: 1471. The target table ViewDec of the INSERT is not insertable-into
Note, this is implemented at the cost of some performance, but not terribly unbearable. I have a table with 1.4 million rows. Here is the test with and without join using a table scan as the access method.
select * from proctable;
-- 1429158 rows in set (1.26 sec)
select * from proctable join (select 1) t;
-- 1429158 rows in set (1.40 sec)
However, for an index lookup access method, this is almost non-existent.
select * from proctable join (select 1) t where id between 100 and 500;
-- 401 rows in set (0.00 sec)
explain select * from proctable join (select 1) t where id between 100 and 500;
+----+-------------+------------+------------+--------+---------------+---------+---------+------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+--------+---------------+---------+---------+------+------+----------+----------------+
| 1 | PRIMARY | <derived2> | NULL | system | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
| 1 | PRIMARY | proctable | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 401 | 100.00 | Using where |
| 2 | DERIVED | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+----+-------------+------------+------------+--------+---------------+---------+---------+------+------+----------+----------------+
I am new to SQL and have been stuck at this one part of my work/assg for a long time and would really appreciate some guide/input!
I have 2 tables. The first table has a codepath that corresponds to the ordercode in the second table, if it matches and the flag is INCL, I should have another column that puts the itemcode specified in table 2 into table 1 and if it's EXCL, i should not include it.
Table1:
| code | codepath |
|:---- |:------: |
| ABC12 | something/NPP3 |
| ABC13 | something/NPP4 |
Table2:
| itemcode | ordercode | flag |
|:---- |:------: |-----:|
| CASH | NPP3 | INCL |
| EXCASH | NPP4 | EXCL |
Result:
| code | codepath | tag |
|:---- |:------: | -----:|
| ABC12 | something/NPP3| CASH |
| ABC13 | something/NPP4| EXCASH |
There are many rows and this is just one example. Not sure if I should join the table but I dont think so as the number of rows dont match and there is no common column as well. Would greatly appreciate any help or guidance!
can you check this?
select t1.code, t1.codepath, t2.itemcode as tag
from
table1 t1 join table2 t2 on SUBSTRING_INDEX(t1.codepath, '/', -1) = t2.ordercode
You would do better to use codepath as the joining column.
It should therefore be indexed, I suggest as a foreign key.
You could join using concat or substring but it is better to avoid functions in joins and enforce consstency with foreign keys. Where possible it is better to use an integer for the primary key to speed up the table scans and indexing.
create table table2 (
itemcode varchar(10) primary key,
ordercode char(5) unique,
flag char(4) );
create table table1 (
code char(5) primary key,
codepath char(5) ,
foreign key fk_codeparth (codepath)
references table2(ordercode));
insert into table2 values
('CASH','NPP3','INCL'),('EXCASH','NPP4','EXCL');
insert into table1 values
('ABC12','NPP3'),('ABC13','NPP4');
select
t1.code,
t1.codepath,
t2.flag tag
from table1 t1
join table2 t2 on t1.codepath = t2.ordercode;
code | codepath | tag
:---- | :------- | :---
ABC12 | NPP3 | INCL
ABC13 | NPP4 | EXCL
*db<>fiddle here727c5a30c04725d5486acdc)
I have table in which has key is primary key. I want to add seqNo key which should be auto incremented but it does not allow to make it as auto increment.
Because there is already one primary key,
Is it possible to make seqNo auto increment? currently seqNo is not present. I want to add it
You can't have two identity columns in a SQL table but you can still create sequences. Here's the link http://technet.microsoft.com/en-us/library/ff878091.aspx
You have the following options.
Make a trigger that increments your column value on every insert statement
Use a sequence, but once a sequence value is generated it will never be generated again (meaning, you would get a gap in your values if your insert fails for some reason)
Vignesh, consider the following...
DROP TABLE IF EXISTS test;
CREATE TABLE test
( testID int(11) NOT NULL
, string varchar(45) DEFAULT NULL
, testInc int(11) NOT NULL AUTO_INCREMENT
, PRIMARY KEY (testID)
, KEY testInc (testInc)
);
INSERT INTO test
(testID
, string
) values
(1
,'Hello'
);
INSERT INTO test (testid,string) SELECT x.testid + y.max_test,string FROM test x JOIN (SELECT MAX(testid) max_test FROM test)y;
INSERT INTO test (testid,string) SELECT x.testid + y.max_test,string FROM test x JOIN (SELECT MAX(testid) max_test FROM test)y;
INSERT INTO test (testid,string) SELECT x.testid + y.max_test,string FROM test x JOIN (SELECT MAX(testid) max_test FROM test)y;
Query OK, 4 rows affected (0.03 sec)
SELECT * FROM test;
+--------+--------+---------+
| testID | string | testInc |
+--------+--------+---------+
| 1 | Hello | 1 |
| 2 | Hello | 2 |
| 3 | Hello | 3 |
| 4 | Hello | 4 |
| 5 | Hello | 6 |
| 6 | Hello | 7 |
| 7 | Hello | 8 |
| 8 | Hello | 9 |
+--------+--------+---------+
Note that the number of rows (8), and the value of testinc (9) are different. This is not what the OP wants. The MAX() trick I've used for generating the PK is also no good, because it's subject to runtime errors.
fiddle of same http://www.sqlfiddle.com/#!2/d29a5b/1
The point is... storing a sequential id is pointless.
I have the following table
SNo Value Item
where Sno is a column which exists in another table also. Right now , what I need is a self incrementing field which will go on incrementing if the value of sno is a constant and then get back to 0 and start incrementing again once the value of sno changes. IS there any way to do this?
Lets say I have four columns:
SNO |Value |Item | AUtoIncrementingField
1 344 a 0
1 345 b 1
1 346 c 2
2 568 d 0
So when I say insert into this table , and the value of SNO changes from whatr it originally was the value of the auto incrementing field should go back to 0. Is there any inbuilt way of doing this, or writing some code on top of mysql to achieve this. If not what other option do I have to uniquely identify each value/item belonging to a certain value of sno?
Whilst this doesn't help you on InnoDB, it's worth pointing out that MyISAM natively supports this functionality. As documented under Using AUTO_INCREMENT:
MyISAM Notes
For MyISAM tables, you can specify AUTO_INCREMENT on a secondary column in a multiple-column index. In this case, the generated value for the AUTO_INCREMENT column is calculated as MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is useful when you want to put data into ordered groups.
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;
Which returns:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
In this case (when the AUTO_INCREMENT column is part of a multiple-column index), AUTO_INCREMENT values are reused if you delete the row with the biggest AUTO_INCREMENT value in any group. This happens even for MyISAM tables, for which AUTO_INCREMENT values normally are not reused.
It's easy to create a database table for storing sequence numbers ; but this design is suited for the event when the sequence is shared for all users. What I want is to create sequence for each group of users : this group can grow at any time because it's a database table , that is the administrator can create a group at any time and users are assigned to a specific group. So how to implement the sequence generation according to a group ?
if you are using myisam
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
Below extracted from above links.
For MyISAM and BDB tables you can specify AUTO_INCREMENT on a
secondary column in a multiple-column index. In this case, the
generated value for the AUTO_INCREMENT column is calculated as
MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is
useful when you want to put data into ordered groups.
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;
Which returns:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
For your case:
CREATE TABLE mytable (
user_id MEDIUMINT NOT NULL AUTO_INCREMENT,
group_id MEDIUMINT NOT NULL,
user_name CHAR(30) NOT NULL,
PRIMARY KEY (group_id,user_id)
) ENGINE=MyISAM;
INSERT INTO mytable (group_id, user_name) VALUES
(1,'alex'),(1,'jenny'),(2,'baz'),(1,'tim'),(2,'danny'),(3,'joe');
SELECT * FROM mytable ORDER BY group_id,user_id;
Returns:
user_id group_id user_name
1 1 alex
2 1 jenny
3 1 tim
1 2 baz
2 2 danny
1 3 joe