How to create customize primary key in MySQL?, example i have table and the table name is X, I have a table field as ID,Code,Name.
I am afraid if I have 1000 users and when they input together will
result in destruction
and i want to :
INSERT INTO `X` (`ID`,`Code`,`Name`) VALUES
('P3K','Alex'), // this primary key is "P3K-1"
('SOS','Force'), // this primary key is "SOS-1"
('P3K','Bash'), // this primary key is "P3K-2"
Right now, i using TRIGGER (BEFORE INSERT) for this, like this one:
SET NEW.`ID` = CONCAT(NEW.`Code`,'-',IFNULL(SUBSTRING_INDEX((
SELECT `x`.`Code` FROM `X` WHERE
X.`Code` = NEW.`Code` and
ORDER BY X.`Code` DESC
LIMIT 1 ),'-',-1),0) + 1))
I did not try this code, but my point is:
User insert
Before insert I checking LAST Primary
IF Null then i set 0, else i cut the symbol (-) and take the last part
I increments (using [+ 1])
Final, i concat CODE and New Number.
am i misguided? LOL, and if true, how to create like this one?
(I THINK) We can do it and maybe no one knows about this, how does AI in MySQL work so perfectly?
Answer from him (https://stackoverflow.com/users/1133682/mjh)
InnoDB is very dependent on PRIMARY KEY using Auto Incremment, if you do not use Auto Incremment then you will spend space. each line by adding at least 6-8 bytes just to make the "HIDDEN PRIMARY KEY", and the best use of innoDB is USE Auto Incremment and do not disturb that key, if you want to add UNIQUE KEY then you just have to CONCAT
Instead of having the hyphenated string as the primary key, you can store the code and number as separate fields, use them together as the primary key, and optionally have the hyphenated string as a generated column. This is how CREATE TABLE would look for such a table
CREATE TABLE X (
Code CHAR(3),
Number INT,
Name VARCHAR(20),
CodeNumber VARCHAR(8) AS (CONCAT(Code, '-', Number)),
PRIMARY KEY (Code, Number)
);
Then you BEFORE INSERT trigger becomes
SET NEW.Number = (1 + IFNULL((SELECT Number FROM X WHERE Code = NEW.Code
ORDER BY Number DESC LIMIT 1), 0))
Related
I have a database named "planning" in which a column named "planning_id" is badly formatted, indeed it's only filled with 0s.
I would like to fill it incrementally with proper IDs; like 1, 2, 3, 4 etc.
I have think about a sql formula like this one:
BEGIN
DECLARE i INT DEFAULT 1;
WHILE (i <= 68) DO
UPDATE planning set planning_id = i;
SET i = i+1;
END WHILE;
END;
But it creates an error (I translate from french to english):
Unrecognized keywords. Near DECLARE.
Any idea ?
If you don't mind the sorting of your columns you can DROP the planning_id and add it again now as Primary Key and with auto_increment like :
ALTER TABLE planning DROP COLUMN planning_id,
ADD COLUMN planning_id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (planning_id);
This way your planning_id will refresh their values in an incremental order (1, 2, 3, 4 and so on).
Check MySQL AUTO INCREMENT Field
Auto-increment allows a unique number to be generated automatically when a new record is inserted into a table.
Often this is the primary key field that we would like to be created automatically every time a new record is inserted
ALTER TABLE table_name AUTO_INCREMENT = start_value;
use auto increment which is the attribute to use when you want MySQL to assign a sequence of numbers automatically to a field (in essence, creating an autonumber field).
Based on my question above, I have a MySQL table called qrc_creation. This table consists of columns like id (auto increment), creation_code, and creation_name. For example, if I want to insert a new creation_name, the ID will auto 1. But, I also want the creation_code to become qrc_00000001, where 1 comes from ID.
Thus, can I know what is the query to do this? Thank you in advance!
You have two options. If you want, the column to autopopulate during insert, you can use MySQL generated columns while defining table schema. However, you cannot use Auto Increment column with this method.
CREATE TABLE `table_1` (
`id` INT(10) ZEROFILL NOT NULL,
`creation_name` VARCHAR(45) NOT NULL,
`creation_code` VARCHAR(55) GENERATED ALWAYS AS (CONCAT(`name`, '_', `id`)),
PRIMARY KEY (`id`));
If you don't want that dedicated column in your table, you can easily get calculated field on your SQL query by using a simple concat function.
SELECT
`id`, `creation_name`, CONCAT(`name`, '_', `id`) AS `creation_code`
FROM
table_1;
Hope it helps.
first of all you need to show your code so that stackoverflow community respond. But still i got your problem and given below is the solution-
CREATE TABLE qrc_creation
(ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
creation_code AS 'qrc' + RIGHT('0000000' + CAST(ID AS VARCHAR(7)), 7) PERSISTED,
creation_name varchar(255),
);
Select * from qrc_creation;
INSERT INTO qrc_creation(creation_name)
VALUES ('Monsen');
Select * from qrc_creation;
Hope you like my answer.
I try to create a table with an INTEGER attribute which should be limited to positive numbers. I know there is an UNSIGNED option, but that does the wrong thing. As it allows adding -10 as a value. It will just make a 10 out of it.
Is it possible to deny a wrong entry? I tried using CHECK
DROP TABLE Produkt;
CREATE TABLE Produkt (
Bezeichnung VARCHAR(237) PRIMARY KEY,
ProduktNr INTEGER NOT NULL,
Produktart VARCHAR(3) DEFAULT "XXX",
CONSTRAINT onlyPositive CHECK(ProduktNr >= 0)
);
But I can still add -10 as a value... What am I doing wrong?
1) In a strict sql_mode if you define your column as
ProduktNr INT UNSIGNED NOT NULL,
and then try to insert a negative value you'll get an error
ERROR 1264 (22003): Out of range value for column 'ProduktNr' at row 1
Here is SQLFiddle demo. Uncomment insert statement and click Build Schema
2) MySQL still lacks support for CHECK constraints. The CHECK clause is parsed but ignored by all storage engines.
3) On a side note: don't use a VARCHAR(237) column as a PRIMARY KEY, especially if you're using InnoDB engine (all secondary indices on the table also include PK values).
I believe you can just add the check without naming the constraint. This seemed to work for me:
CREATE TABLE Produkt (
Bezeichnung VARCHAR(237),
ProduktNr INTEGER NOT NULL,
Produktart VARCHAR(3) DEFAULT "XXX",
PRIMARY KEY (Bezeichnung),
CHECK(ProduktNr >= 0)
);
I also moved the declaration of the primary key. I'm not 100% certain that you can declare a key the same time as a field, but I did put what I knew.
Note: Apologies if this is a duplicate but I can't find a solution.
I have two databases (one dev and one live) which have exactly the same schema.
To make things easier to explain, assume I have a 'customer' table and a 'quote' table. Both tables have auto increment ids and the quote table has a 'customerid' column that serves as a foreign key to the customer table.
My problem is that I have some rows in my dev database that I want to copy to the live database. When I copy the customer rows I can easily get a new id, but how can i get the new id to be assigned to the 'child' quote table rows?
I know I can manually script out INSERTS to overcome the problem but is there an easier way to do this?
EDIT:
This is a simplified example, I have about 15 tables all of which form a hierarchy using auto-increments and foreign keys. There is considerably more data in the live database so the new ids will be bigger (e.g. dev.customer.id = 4, live.customer.id = 54)
Easiest way without changing any IDs.
Ensure that you are currently in the table where the record you want to copy is in (source db).
Run the following command:
INSERT INTO to_database.to_table
SELECT * FROM from_table WHERE some_id = 123;
No need to specify columns if there is no need to remap anything.
Hope that helps!
I eventually managed to do this (as per my comment) but in order to do so I had to write some code. In the end I created some dummy tables that kept track of the old id against new id so. When copying over records with FK constraints I just looked up the new id based on the old. A bit long winded but it worked.
This post is getting on a bit now so I've marked this as the answer. If anyone out there has better ideas/solutions that work I'll happily 'unmark' it as the accepted answer.
EDIT: As requested here is some pseudo-code that I hope explains how I did it.
I have the two related tables as follows:
CREATE TABLE tblCustomers (
Id int NOT NULL AUTO_INCREMENT,
Name varchar(50) DEFAULT NULL,
Address varchar(255) DEFAULT NULL,
PRIMARY KEY (Id)
)
ENGINE = MYISAM
ROW_FORMAT = fixed;
CREATE TABLE tblQuotes (
Id int NOT NULL AUTO_INCREMENT,
CustomerId int(11) DEFAULT NULL,
QuoteReference varchar(50) DEFAULT NULL,
PRIMARY KEY (Id)
)
ENGINE = MYISAM
ROW_FORMAT = fixed;
I create an extra table that I will use to track old ids against new ids
CREATE TABLE tblLookupId (
Id int NOT NULL AUTO_INCREMENT,
TableName varchar(50) DEFAULT NULL,
OldId int DEFAULT NULL,
NewId int DEFAULT NULL,
PRIMARY KEY (Id)
)
ENGINE = MYISAM
ROW_FORMAT = fixed;
The idea is that I copy the tblCustomer rows one at a time and track the ids as I go, like this:
// copy each customer row from dev to live and track each old and new id
//
foreach (customer in tblCustomers)
{
// track the old id
var oldid = customer.id; // e.g. 1
// insert the new record into the target database
INSERT newdb.tblCustomers (...) VALUES (...);
// get the new id
var newid = SELECT LAST_INSERT_ID() // e.g. 245
// insert the old id and the new id in the id lookup table
INSERT idlookup (TableName, OldId, NewId) VALUES ('tblCustomers', oldid, newid); // this maps 1->245 for tblCustomers
}
When I come to copy the table (tblQuote) with the foreign key I have to first lookup the new id based on the old.
// copy each quote row from dev to live and lookup the foreign key (customer) from the lookup table
//
foreach(quote in tblQuotes)
{
// get the old foreign key value
var oldcustomerid = quote.CustomerId; // e.g 1
// lookup the new value
var newcustomerid = SELECT newid FROM tblIdLookup WHERE TableName='tblCustomers' AND oldid=oldcustomerid; // returns 245
// insert the quote record
INSERT tblQuotes (CustomerId, ...) VALUES (newcustomerid, ...);
}
I've tried to keep this short and to the point (and language agnostic) so the technique can be seen. In my real scenario I had around 15 'cascading' tables so I had to track the new ids of every table not just tblCustomer
Use INSERT ... SELECT:
insert into your_table (c1, c2, ...)
select c1, c2, ...
from your_table
where c1, c2, ... are all the columns except id.
actually this already worked and i have no idea what i've changed so that i run into this problem now. Tried nearly everything.
The case:
I have the following query. The variable $DB-id is an empty string if the content i want to save is new. The field module_id is my primary key. What happens is that this query always updates the row with the module_id => 0.
The problem
Passing an empty variable as the primary key always updates row 0 instead of inserting a new one.
$this->db->query("INSERT INTO modules_text
(
module_id,
module_content,
module_page_idx,
module_post_id
)
VALUES (
'{$DB_id}',
'{$content['text']}',
'{$content['idx']}',
'{$post_id}'
)
ON DUPLICATE KEY
UPDATE module_content = '{$content['text']}',
module_page_idx = '{$content['idx']}'
");
Does anybody have an idea how i can tell MYSQL to create a new row??? Any help is very appreciated!!!! Thank you very much!!!
Saludos Sacha!
You may need to set your primary key field to auto increment. An example is below.
CREATE TABLE tablename (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id))
I would assume you need to give the UPDATE a WHERE?
eg:
$this->db->query("INSERT INTO modules_text
(
module_id,
module_content,
module_page_idx,
module_post_id
)
VALUES (
'{$DB_id}',
'{$content['text']}',
'{$content['idx']}',
'{$post_id}'
)
ON DUPLICATE KEY
UPDATE `module_content` = '{$content['text']}',
`module_page_idx` = '{$content['idx']}'
WHERE
`module_id` = '{$content['id']}'
");
Don't hold me to it xD, just a guess at first glance.