which middle safer for mes to recover and Sort indexes primary key, avoiding unnecessary update throughout the database? Can you show me any examples?
I just wanna that primary keys were constant and dynamic.I just wanna that primary keys were constraint and dinamic
ps: MySQL Database
User's Table
|| user_id || user_first_name || user_last_name
#1 Alexandre Doria
#2 Ilya Bursov
#3 Anybody Anybody
So, if i DELETE the #2 row, and INSERT a new row, the primary key of #3 row is duplicated.
My PHP code here:
$user_id_cont = mysql_query("select 'user_id' from user");
$user_id = mysql_num_rows($user_id_cont)+1;
It absolutely wrong to calculate primary keys as it done in your code
First of all - change user_id column to be primary key (it will be unique too then), also set it to be auto_increment, so your table create statement must be:
create table sample_users (
`user_id` int unsigned not null auto_increment,
`first` varchar(255),
`last` varchar(255),
primary key (`user_id`)
);
next, you need to insert data into your table, so you can just insert it:
INSERT into `sample_users` (`first`, `last`) values('fname', 'lname');
INSERT into `sample_users` (`first`, `last`) values('fname2', 'lname2');
...
mysql will generate appropriate user_id for each row, and even if you delete some of them - mysql still will provide you with unique values
additional case is - if you need to know what id is generated by mysql, you can use PHP mysql_insert_id or MySQL LAST_INSERT_ID functions for that
just for notice: wrong method, but it will work for "school project", change your code to:
$user_id_cont = mysql_query("select max('user_id') from user");
$user_id = mysql_fetch_array($user_id_cont, MYSQL_NUM);
$user_id = $user_id[0]+1;
Related
I'm currently having issues with inserting values into a database table that uses a foreign key from another table to align the is together. The tables are pretty simple. One holds information about a project, and the other hold values for the project images. Here they are in detail.
The projects table
project_id int(50) PRIMARY KEY NOT NULL AUTO_INCREMENT,
project_name varchar(50) NOT NULL,
project_permitted timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "The date that the project took place.",
project_in varchar(50) NOT NULL COMMENT 'The place where the project took place (ie the city and state).',
project_type varchar(50) NOT NULL COMMENT 'The project type (ie residentual, commercial, etc).',
project_description longtext,
project_published timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Here is the second table called project_images
image_id int(50) PRIMARY KEY NOT NULL AUTO_INCREMENT,
project_id int(50),
image_url varchar(50) NOT NULL,
CONSTRAINT fk_projects FOREIGN KEY (project_id) REFERENCES projects(project_id)
What I am trying to do is insert values into the second table using the project_id from the projects table using a subquery. That query looks like this:
insert into project_images (project_id, project_url, project_description)
values (
(select project_id from projects where project_name = 'The Venue'),
"images/theVenue.png",
"The Venue: an appartment complex in Austin, Texas."
)
With this query I keep getting an error that says
something to the effect of "You are missing a comma or closing bracket
near project_id.
Can anyone help or point out the best way to handle this situation.
Modify your query to be like
insert into project_images (project_id, project_url, project_description)
select project_id ,
"images/theVenue.png",
"The Venue: an appartment complex in Austin, Texas."
from projects where project_name = 'The Venue';
After looking into this question a bit more, it seems that you cannot use a subquery the way I am using it to get the value of a column, However, the column can be inserted directly so long as the foreign key points to a primary key from another table that has already be inserted. The whole point to using this query was for a PHP project, so I guess I'll just do a select query in a project to get its ID then add that to the sql that queries the project_images table. This seems to be the only way to do that.
So I'm new to the use of multiple tables. Prior to today, 1 table suited my needs (and I could probably get away with using 1 here as well).
I'm creating a plugin for a game I play but I'm using a MySQL database to store all the information. I have 3 tables, Players, Warners and Warns. Warns has 2 foreign keys in it (one referencing to Players and the other to Warners).
At the moment I need to do 3 queries. Add the information to Players & Warners, and then to Warns. Is there a way I can cut down the amount of queries and what would happen if I were to just omit the first 2 queries?
Query Examples:
INSERT INTO slimewarnsplayers VALUES ('123e4567-e89b-12d3-a456-426655440000', 'Spedwards');
INSERT INTO slimewarnswarners VALUES ('f47ac10b-58cc-4372-a567-0e02b2c3d479', '_Sped');
INSERT INTO slimewarnswarns VALUES ('', '123e4567-e89b-12d3-a456-426655440000', 'f47ac10b-58cc-4372-a567-0e02b2c3d479', 'spamming', 'medium');
Tables:
CREATE TABLE IF NOT EXISTS SlimeWarnsPlayers (
uuid VARCHAR(36) NOT NULL,
name VARCHAR(26) NOT NULL,
PRIMARY KEY (uuid)
);
CREATE TABLE IF NOT EXISTS SlimeWarnsWarners (
uuid VARCHAR(36) NOT NULL,
name VARCHAR(26) NOT NULL,
PRIMARY KEY (uuid)
);
CREATE TABLE IF NOT EXISTS SlimeWarnsWarns (
id INT NOT NULL AUTO_INCREMENT,
pUUID VARCHAR(36) NOT NULL,
wUUID VARCHAR(36) NOT NULL,
warning VARCHAR(60) NOT NULL,
level VARCHAR(60) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (pUUID) REFERENCES SlimeWarnsPlayers(uuid),
FOREIGN KEY (wUUID) REFERENCES SlimeWarnsWarners(uuid)
);
Is there a way I can cut down the amount of queries?
NO, I don't see that. From your posted INSERT statements (as depicted below) it's clear that those are 3 different tables and you are inserting different data to them. so, you will have to perform the INSERT operation separately for them.
INSERT INTO slimewarnsplayers
INSERT INTO slimewarnswarners
INSERT INTO slimewarnswarns
Another option would be (May not be considered good), creating a procedure which will accept the data and table name and create a prepared statement/dynamic query to achieve what you are saying. something like (A sample pseudo code)
create procedure sp_insert(tablename varchar(10), data1 varchar(10),
data2 varchar(10))
as
begin
--dynamic query here
INSERT INTO tablename VALUES (data1, data2);
end
To explain further, you can then call this procedure from your application end passing the required data. Do note that, if you have a Foreign Key relationship with other table then you will have to catch the last inserted key from your master table and then pass the same to procedure.
No, you can't insert into multiple tables in one MySQL command. You can however use transactions.
BEGIN;
INSERT INTO slimewarnsplayers VALUES(.....);
last_id = LAST_INSERT_ID()
INSERT INTO SlimeWarnsWarners VALUES(last_id, ....);
INSERT INTO SlimeWarnsWarns VALUES(last_id, ....);
COMMIT;
I would also take a look at http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
and this post MySQL Insert into multiple tables? (Database normalization?)
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.
I need to insert records, but if the records exist do a replace instead. Here is what I am currently using:
$sessionDate = date("Y-m-d H:i:s");
foreach($tmpVP as $sessionVP) {
$res = mysql_query("INSERT INTO sessions
(sessionID,sessionDate,sessionVS,sessionVP)
VALUES('$sessionID','$sessionDate','$sessionVS',
'$sessionVP')") ;
}
What I really need is to update any records matching sessionID, sessionVS, and sessionVP and insert new records that don't match.
EDIT:
Table definition
CREATE TABLE `sessions` (
`ID` bigint(20) NOT NULL auto_increment,
`sessionID` varchar(36) NOT NULL,
`sessionDate` datetime NOT NULL,
`sessionUser` bigint(20) NOT NULL,
`sessionVS` varchar(255) NOT NULL,
`sessionVP` bigint(20) NOT NULL,
`reserved` int(11) NOT NULL,
PRIMARY KEY (`ID`),
KEY `ID` (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=88 DEFAULT CHARSET=utf8
sessionID, sessionVP, and sessionVS are not unique. Sample:
sessionID sessionDate sessionUser sessionVS sessionVP
0t1m58q9ktejuhqlrjqglcoia0 2010-06-20 09:20:53 0 111111 144268736
0t1m58q9ktejuhqlrjqglcoia0 2010-06-20 09:20:53 0 111111 144268819
0t1m58q9ktejuhqlrjqglcoia0 2010-06-20 09:20:53 0 111111 144268880
So, if I have a new record with 0t1m58q9ktejuhqlrjqglcoia0, 111111, and `144268880' I need to update row #3 instead of adding row #4.
Firstly you should add a unique index on (sessionID, sessionVP, sessionVS). You can do this using the following command:
CREATE UNIQUE INDEX ux_sessions_sessionid_sessionvs_sessionvp
ON sessions (sessionID, sessionVS, sessionVP)
Then there are two relatively simple ways to insert or update in MySQL. The first is to use ON DUPLICATE UPDATE:
INSERT INTO sessions
(sessionID,sessionDate,sessionVS,sessionVP)
VALUES
('$sessionID', '$sessionDate', '$sessionVS', '$sessionVP')
ON DUPLICATE KEY UPDATE sessionDate = '$sessionDate'
There other is to use REPLACE:
REPLACE INTO sessions
(sessionID,sessionDate,sessionVS,sessionVP)
VALUES
('$sessionID', '$sessionDate', '$sessionVS', '$sessionVP')
The second is slightly more concise, but has the disadvantage that it internally causes a delete followed by an insert.
There are also a few other issues:
You don't need both a primary key index and an ordinary index on ID. Remove the ordinary index as it is redundant.
You may have an SQL vulnerability. If you have not already validated the input you might want to consider protecting yourself by using mysql_real_escape_string or intval as appropriate. Alternatively you could look at using query parameters.
You are not checking for error conditions. Consider using trigger_error so that if your query has an error you can see what the error is. Seeing the error message can save you a lot of time debugging.
mysql_query("...") or trigger_error(mysql_error());
You might take a look at INSERT ... ON DUPLICATE KEY UPDATE: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
Add an unique key on (sessionID, sessionVS, sessionVP), then use REPLACE instead of INSERT (just substitute the word, syntax is the same).
Based on your table structure, I mean the primary keys you can use
$res = mysql_query("REPLACE INTO sessions
(sessionID,sessionDate,sessionVS,sessionVP)
VALUES('$sessionID','$sessionDate','$sessionVS',
'$sessionVP')") ;
Are the values part of the primary key? If yes, take a look at: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html