Basically, I have two tables: images and servers. When I want to insert a row into the images table, I need to specify a s_id as one of the fields. Problem is, I only have name, which is another field in the servers table. I need to find what s_id belongs to name, and then use that in my INSERT INTO query on the images table.
Maybe this image will help:
http://i.imgur.com/rYXbW.png
I only know the name field from the servers table, and I need to use it to get the s_id field from the servers table. When I have that, I can use it in my INSERT INTO query, as it's a foreign key.
I found this:
http://www.1keydata.com/sql/sqlinsert.html
But it just confused me even more.
One solution would be to run two queries. One to get the s_id, and one to run the insert query. But I'd like to limit the amount of queries I run if there's a reasonable alternative.
Thanks!
You can use the INSERT ... SELECT form, something like this (with real column names and values of course):
INSERT INTO images (s_id, u_id, name, filename, uploaded)
SELECT s_id, ...
FROM servers
WHERE name = 'the name'
I don't know where you're getting the u_id, name, filename, or uploaded column values for images but you can include them as literal values in the SELECT:
INSERT INTO images (s_id, u_id, name, filename, uploaded)
SELECT s_id, 11, 'pancakes', 'pancakes.jpg', '2011-05-28 11:23:42'
FROM servers
WHERE name = 'the name'
This sort of thing will insert multiple values if servers.name is not unique.
You should be able to do something like this, but you'll need to fill in the items in <> with the values you want to insert.
INSERT INTO images (s_id, u_id, name, filename, uploaded)
(SELECT s_id, <u_id>, <name>, <filename>, <uploaded>
FROM imgstore.servers
WHERE name = #server_name)
This is the syntax for SQL Server, but I think it will work with MySQL as well.
Here's an article on INSERT ... SELECT Syntax
Please see my comment above regarding a potential data integrity issue. I am assuming that the name field in your server table has a unique constraint placed on it.
There are a couple of ways that you can approach this INSERT, and I'm sure that some are better than others. I make no claim that my way is the best way, but it should work. I don't know how you're writing this query, so I'm going to use #FieldValue to represent the variable input. My approach is to use a subquery in your insert statement to get the data that you require.
INSERT INTO images (field1, field2... s_id) VALUES ('#field1val', '#field2val'... (SELECT s_id FROM servers WHERE name='#nameval'));
Related
I have a table called: Orders (Id, FK_Customer_Id, Comments, PaymentMethod, DeliverTime), which is used to store order information of a online retailer website, and also a table: Order_Items (Id, FK_Order_Id, FK_Product_Id, Quantity), to store the details of an order.
once the user submit an order, I need to save the information to the two table, but I don't know how to solve the concurrency problem.
Because, I should first insert into Orders table, then get the Order_Id and insert this Id to Order_Items table. I try to use "SELECT LAST_INSERT_ID() AS OrderId". But what if I insert into order and before I can get the Id, someone else insert another Order? Then the above statement will get the Id of the new inserted order, which is not my order anymore.
Please help me and let me know how to do it, or if I design the order/orderItem in a wrong way.
P.S. I m using angular 2 as front-end and node.js to create APIs and MySQL as DB.
Thank you in advance.
I would separate the operations.
This will prevent any unexpected "race" affects with inserting records.
So, first, insert the order.
Then, second, confirm that the insert query was successful by asking for the "insert id" with something like mysql_insert_id() or whatever the node.js equivalent is.
Then, third, once you have that id, you can safely insert the details of the order.
I have a table (People) with columns (id, name, year). Is there any way I can get all the ids ( SELECT id FROM people ) and use them for creating new rows in other table (people_id, additional_info). I mean that for every id in table People I want to add new row in other table containing the id and some additional information. Maybe something like for-loop is needed here ?
Well, usually you have information on a person and write one record with this information. It makes litte sense to write empty records for all persons. Moreover, when it's just one record per person, why not simply add an information column to the people table?
Anyway, you can create mock records thus:
insert into people_info (people_id, additional_info)
select id, null from people;
Insert into targetTable (id, additional_info)
select id,'additionalinfo' from PEOPLE
No for loop is needed, Just use the above query.
You can use INSERT ... SELECT syntax for MySQL to insert the rows into people_info table (documentation here).
e.g.
insert into people_info(...)
select (...) from people; <and posibly other tables>
I am trying to display where a record has multiple categories though my query only appears to be showing the first instance. I need for the query to be displaying the domain multiple times for each category it appears in
The SQL statement I have is
SELECT domains.*, category.*
FROM domains,category
WHERE category.id IN (domains.category_id)
Which gives me the below results
You should not store numeric values in a string. Bad, bad idea. You should use a proper junction table and the right SQL constructs.
Sometimes, we are stuck with other people's bad design decisions. MySQL offers find_in_set() to help in this situation:
where find_in_set(category.id, domains.category_id) > 0
Use find_in_set().
SELECT domains.*, category.*
FROM domains,category
WHERE find_in_set (category.id ,domains.category_id)
But it is very bad db design to store fk as a csv.
As others have pointed out, you can use FIND_NI_SET() as a workaround to solve your problem.
My suggestion is that you refactor your code and database a bit. Storing values in CSV format stored in a single column is almost always a bad idea.
As Gordon Linoff correctly points out you'd be better off if you'd create an additional table to store the category_id values:
CREATE TABLE domain_categories (domain_id INT, category_id INT, PRIMARY KEY (domain_id, category_id));
That's assuming you want to enfore that each category is only stored once against each domain. If you don't, just drop the primary key.
You'd then insert your IDs into this new table:
INSERT INTO domain_categories (domain_id, category_id) VALUES (2,6),(2,8);
or
INSERT INTO domain_categories (domain_id, category_id) VALUES (4,3);
INSERT INTO domain_categories (domain_id, category_id) VALUES (4,11);
INSERT INTO domain_categories (domain_id, category_id) VALUES (20,3);
Now that you have properly stored the data you can easily query as needed:
SELECT domains.*,category,*
FROM domains
JOIN domain_category ON (domain_category.domain_id=domains.id)
JOIN category ON (category.id=domain_category.category_id);
Using MySQL quirks you can even show the category_id column in CSV format.
SELECT domains.*, GROUP_CONCAT(DISTINCT domain_category.category_id)
FROM domains
JOIN domain_category ON (domain_category.domain_id=domains.id)
GROUP BY domains.id;
I need to add data to a MySQL database like that:
Person:
pId, nameId, titleId, age
Name:
nameId, name
Title:
titleId, title
I don't want to have any names or title more then once in the db so I didn't see a solution with LAST_INSERT_ID()
My approach looks like that:
INSERT IGNORE INTO Name(name) VALUES ("Peter");
INSERT IGNORE INTO Title(title) VALUES ("Astronaut");
INSERT INTO Person(nameId, titleId, age) VALUES ((SELECT nameId FROM Name WHERE name = "Peter"), (SELECT nameId FROM Name WHERE name = "Astronaut"), 33);
But I guess that's a quite dirty approach!?
If possible I want to add multiple persons with one query and without having anything more then one times in db.
Is this possible in a nice way? Thanks!
You could put title and name as two columns of your table and then:
set one UNIQUE index on each column if you don"t want to have two titles or two names identical in the DB
or set an UNIQUE index on (title,name) if you don't want to have two entries having both the same name and the same title.
If you really want to have separate tables, you could do as you suggested in your post, but wrapping all your insert statements in a TRANSACTION to allow rollback if you detect a duplicate somewhere.
See Design dilemma: If e-mail address already used, send e-mail "e-mail address already registered", but can't because can't add duplicate to table which appear to be exactly the same problem, but having name & email instead of name & titles.
START TRANSACTION;
INSERT INTO title(value) VALUES ("Prof.");
SELECT LAST_INSERT_ID() INTO #title_id;
-- Instead of using user-defined variable,
-- you should be able to use the last_insert_id
-- equivalent from the host language MySQL driver.
INSERT INTO username(value) VALUES ("Sylvain");
SELECT LAST_INSERT_ID() INTO #username_id;
-- Instead of using user-defined variable,
-- you should be able to use the last_insert_id
-- equivalent from the host language MySQL driver.
INSERT INTO account(username_id, email_id) VALUES (#username_id,#title_id);
COMMIT;
See LAST_INSERT_ID()
A third solution would be to SELECT before doing you insert to see in the entry are already present. But personally I wouldn't push to the check-before-set approach at the very least, this will require an extra query which is mostly superfluous if you use correctly indexes.
I'm using MySQL 4.1. Some tables have duplicates entries that go against the constraints.
When I try to group rows, MySQL doesn't recognise the rows as being similar.
Example:
Table A has a column "Name" with the Unique proprety.
The table contains one row with the name 'Hach?' and one row with the same name but a square at the end instead of the '?' (which I can't reproduce in this textfield)
A "Group by" on these 2 rows return 2 separate rows
This cause several problems including the fact that I can't export and reimport the database. On reimporting an error mentions that a Insert has failed because it violates a constraint.
In theory I could try to import, wait for the first error, fix the import script and the original DB, and repeat. In pratice, that would take forever.
Is there a way to list all the anomalies or force the database to recheck constraints (and list all the values/rows that go against them) ?
I can supply the .MYD file if it can be helpful.
To list all the anomalies:
SELECT name, count(*) FROM TableA GROUP BY name HAVING count(*) > 1;
There are a few ways to tackle deleting the dups and your path will depend heavily on the number of dups you have.
See this SO question for ways of removing those from your table.
Here is the solution I provided there:
-- Setup for example
create table people (fname varchar(10), lname varchar(10));
insert into people values ('Bob', 'Newhart');
insert into people values ('Bob', 'Newhart');
insert into people values ('Bill', 'Cosby');
insert into people values ('Jim', 'Gaffigan');
insert into people values ('Jim', 'Gaffigan');
insert into people values ('Adam', 'Sandler');
-- Show table with duplicates
select * from people;
-- Create table with one version of each duplicate record
create table dups as
select distinct fname, lname, count(*)
from people group by fname, lname
having count(*) > 1;
-- Delete all matching duplicate records
delete people from people inner join dups
on people.fname = dups.fname AND
people.lname = dups.lname;
-- Insert single record of each dup back into table
insert into people select fname, lname from dups;
-- Show Fixed table
select * from people;
Create a new table, select all rows and group by the unique key (in the example column name) and insert in the new table.
To find out what is that character, do the following query:
SELECT HEX(Name) FROM TableName WHERE Name LIKE 'Hach%'
You will se the ascii code of that 'square'.
If that character is 'x', you could update like this:(but if that column is Unique you will have some errors)
UPDATE TableName SET Name=TRIM(TRAILING 'x' FROM Name);
I'll assume this is a MySQL 4.1 random bug. Somes values are just changing on their own for no particular reason even if they violates some MySQL constraints. MySQL is simply ignoring those violations.
To solve my problem, I will write a prog that tries to resinsert every line of data in the same table (to be precise : another table with the same caracteristics) and log every instance of failures.
I will leave the incident open for a while in case someone gets the same problem and someone else finds a more practical solution.