Insert a greatest value (max+1) - mysql

I have a table (foo) where I already have a PK on id:
id name rank
-----------------------
1 AAAA 2
2 BBBB 1
I want to insert a new row where I know the values of column id and name and want rank to take a value greater than any other value in the same column in preceding rows (similar to what auto_increment does for us).
i.e. if I were to add a row with value = CCCC, the rank column should have a value 3. I need to do this in a compound statement if possible. I tried the following which does not work.
insert into foo (`name`, `rank`)
values ('CCCC', (select max(`rank`) from `foo`))
Which gives me the following error:
You can't specify target table 'foo' for update in FROM clause
Note: I would ideally like to have the rank column as an auto_increment field, but apparently that's not allowed either, since I already have a PK.
PS: I need to be able to execute this statement from PHP without using stored procedures.

Try this first, it being derived instantly from your post:
INSERT INTO foo (`name`, `rank`)
SELECT 'CCCC', (MAX(`rank`) + 1) AS rank
FROM `foo`
Then using PDO, I think this'll work:
...
$sql = "INSERT INTO foo (`name`, `rank`) SELECT ?, (MAX(`rank`) + 1) AS rank FROM `foo`"
$name = "CCCC";
$st = $pd->prepare($sql);
$st->bindValue(1, $name);
try {
$retval = $st->execute();
} catch (PDOException $pdoex) {
...
Not sure if I got in syntactically correct but that should be about the gist of it ... I think
Err.. lemme know if the SQL works, at least :D

Related

Insert type id in table

How to insert score with value and score_id ? At server im know only score_type.name and score.value. How i can insert new score with score_type ? If score_type name exsist just get id and insert, else create, get id and insert.
First try to create the score_type if it doesn't exist:
INSERT IGNORE INTO score_type (name) VALUES ("type_name");
Then use INSERT ... SELECT to insert the ID into the score table:
INSERT INTO score (value, score_type_id, player_id)
SELECT 123, id, "player_name"
FROM score_type
WHERE name = "type_name";
The first INSERT assumes you have a unique index on score_type.name. IGNORE means to fail silently if you try to insert a duplicate name.
Replace 123 and player_name with the known score.value and score.player_id.
If I understood your question correctly, you want to fill the score_type_id dynamically by selecting it using the name:
INSERT INTO `score`(`value`, `score_type_id`, `player_id`) VALUES (1337, (SELECT id FROM score_type WHERE score_type.name = "test") ,"maio290");
The trick is just to use another query instead of a fixed value.

MySQL: how to update column using value before change

There is a table with three column: id, field1, field2.
And there is a row: id=1, field1=1, field2=1.
Run a update SQL: UPDATE my_table SET field1=field2+1, field2=field1+1 WHERE id=1;
I expected the result is: id=1, field1=2, field2=2. But in fact I got: id=1, field1=2, field2=3. Because when calculating field2=field1+1, the value of field1 has changed!
I figure out a SQL to solve this problem:
UPDATE my_table dest, (SELECT * FROM my_table) src
SET dest.field1=src.field2+1, dest.field2=src.field1+1
WHERE dest.id=1;
However I want to insert a record, and if the row was existed then do a update just like above.
INSERT INTO my_table (id, field1, field2) VALUES(1, 1, 1)
ON DUPLICATE KEY UPDATE
field1=field2+1, field2=field1+1;
This SQL has problem same as the first SQL. So how can I do this update using the value before change with ON DUPLICATE KEY UPDATE clause?
Thanks for any help!
Couldn't think of anything else but a temp variable. However, couldn't think of a way to make SQL syntax work, other than this:
set #temp = 0;
update test.test set
f1 = (#temp:=f1),
f1 = f2 + 1,
f2 = #temp + 1
where id = 1;
Hope this helps, and hope even more it helps you find a better way :)
I find a trick way to do this.
Use the IF clause to create temp variable. Field update use temp variable to calculate.
INSERT INTO my_table (id, f1, f2) VALUES(1, 1, 1)
ON DUPLICATE KEY UPDATE
id=IF((#t1:=f1 & #t2:=f2), 1, 1), f1=#t2+1, f2=#t1+1;
There is some point to notice:
The performance is a bit slow. Especially copy TEXT value to temp variable.
If field id need to use IF clause, the expr will be more complicated like:
((#t1:=f1 & #t2:=f2) || TRUE) AND (Your Condition)

INSERT ... SELECT(insert many rows)

i want to insert the scholar's id to the tblinbox. Here is my query:
$sql = "INSERT INTO tblinbox VALUES ('','$sender','$type','$subject','$LRN','$content','$date', '$newyearLevel','','$userType','THIS_IS_FOR_THE_ID_OF_THE_SCHOLAR')
SELECT id FROM tblscholar WHERE schoYear = '$newyearLevel'";
my problem is,it is not inserting. what will i change in my query?
INSERT ... SELECT syntax does not allow for VALUES declaration. The values ARE the results returned from the SELECT.
See the documentation here: http://dev.mysql.com/doc/refman/5.6/en/insert-select.html
I honestly am not fully sure what you are trying to do with your insert. If you are trying to insert the same values held in your variables for each id value from the tblscholar table then perhaps you need to do something like this:
INSERT INTO tblinbox
/*
maybe add column definitions here to make it clearer
column definitions could look like this:
(
someField,
type,
subject,
LRN,
content,
`date`,
newyearLevel,
someOtherField,
userType,
id
)
*/
SELECT
'',
'$sender',
'$type',
'$subject',
'$LRN',
'$content',
'$date',
'$newyearLevel',
'',
'$userType',
id
FROM tblscholar
WHERE schoYear = '$newyearLevel'
An INSERT statement supports either a VALUES clause followed by a row of values, or else a SELECT query with columns to match the columns of the table you want to insert into.
But not both!
But you can add constant values into your SELECT query:
$sql = "INSERT INTO tblinbox
SELECT '','$sender','$type','$subject','$LRN','$content','$date',
'$newyearLevel','','$userType', id
FROM tblscholar WHERE schoYear = '$newyearLevel'";
considering id is the first column in your insert statement, try this
$sql = "INSERT INTO tblinbox VALUES ((SELECT id FROM tblscholar WHERE schoYear = '$newyearLevel'),'$sender','$type','$subject','$LRN','$content','$date', '$newyearLevel','','$userType')";
You can insert values either fetching values form another table or providing values as follows:
Way 1:
INSERT INTO tblinbox(coloumn_name1,coloumn_name2) VALUES (value1,value2);
Way 2:
INSERT INTO tblinbox(coloumn_name1,coloumn_name2) SELECT value1,value2 from tblscholer where schoYear= '$newyearLevel';

How make insert if select rows == '0' in one query?

In mysql, I have the following:
Structure Table:
id(int primary key)
name(varchar 100 unique)
Values:
id name
1 test
2 test1
I have two queries:
1) SELECT count(*) FROM Table WHERE name='test'
2) if count select rows == 0 second query INSERT INTO Table (name) VALUES ('test')
I know that may be use:
$res = mysql(SELECT count(*) as count FROM Table WHERE name='test');
// where mysql function make query in db
$i = $res -> fetch_assoc();
if($i['count'] < 1 ){$res = mysql(INSERT INTO Table (name) VALUES ('test');}
But I would like know how to make two query in one query.
How do I make one query inside of two?
You can do it with a simple trick, like this:
insert into Table1(name)
select 'test' from dual
where not exists(select 1 from Table1 where name='test');
This will even work if you do not have a primary key on this column.
Explanation: DUAL is a special dummy table that is only referenced here to enable the WHERE clause. You would not be able to have a statement without a FROM clause (like select 'test' where not exists(select 1 from Table1 where name='test')) as it will be incomplete.
Assuming your name column has a UNIQUE constraint, just add IGNORE to the INSERT statement.
INSERT IGNORE INTO Table (name) VALUES ('test')
This will skip the insertion if a record already exists for a particular value and return 0 affected rows. Note that a primary key is also considered a UNIQUE constraint.
If the name column doesn't have such a constraint, I would advice that you add one:
ALTER TABLE `Table` ADD UNIQUE(name)
See also the documentation for INSERT
If you don't need to check whether there is duplication, other's suggestion is good for you. But you need, use 'INSERT' and check error number like this:
mysql_query('INSERT INTO ...');
if (mysql_errno() == 1062)
{
echo "duplicated";
}
else
{
echo "inserted";
}
(I know mysql_XXXX() is deprecated.. just example)

INSERT INTO with SubQuery MySQL

I have this Statement:
INSERT INTO qa_costpriceslog (item_code, invoice_code, item_costprice)
VALUES (1, 2, (SELECT item_costprice FROM qa_items WHERE item_code = 1));
I'm trying to insert a value copy the same data of item_costprice, but show me the error:
Error Code: 1136. Column count doesn't match value count at row 1
How i can solve this?
Use numeric literals with aliases inside a SELECT statement. No () are necessary around the SELECT component.
INSERT INTO qa_costpriceslog (item_code, invoice_code, item_costprice)
SELECT
/* Literal number values with column aliases */
1 AS item_code,
2 AS invoice_code,
item_costprice
FROM qa_items
WHERE item_code = 1;
Note that in context of an INSERT INTO...SELECT, the aliases are not actually necessary and you can just SELECT 1, 2, item_costprice, but in a normal SELECT you'll need the aliases to access the columns returned.
You can just simply e.g.
INSERT INTO modulesToSections (fk_moduleId, fk_sectionId, `order`) VALUES
((SELECT id FROM modules WHERE title="Top bar"),0,-100);
I was disappointed at the "all or nothing" answers. I needed (again) to INSERT some data and SELECT an id from an existing table.
INSERT INTO table1 (id_table2, name) VALUES ((SELECT id FROM table2 LIMIT 1), 'Example');
The sub-select on an INSERT query should use parenthesis in addition to the comma as deliminators.
For those having trouble with using a SELECT within an INSERT I recommend testing your SELECT independently first and ensuring that the correct number of columns match for both queries.
Your insert statement contains too many columns on the left-hand side or not enough columns on the right hand side. The part before the VALUES has 7 columns listed, but the second part after VALUES only has 3 columns returned: 1, 2, then the sub-query only returns 1 column.
EDIT: Well, it did before someone modified the query....
As a sidenote to the good answer of Michael Berkowski:
You can also dynamically add fields (or have them prepared if you're working with php skripts) like so:
INSERT INTO table_a(col1, col2, col3)
SELECT
col1,
col2,
CURRENT_TIMESTAMP()
FROM table_B
WHERE b.col1 = a.col1;
If you need to transfer without adding new data, you can use NULL as a placeholder.
If you have multiple string values you want to add, you can put them into a temporary table and then cross join it with the value you want.
-- Create temp table
CREATE TEMPORARY TABLE NewStrings (
NewString VARCHAR(50)
);
-- Populate temp table
INSERT INTO NewStrings (NewString) VALUES ('Hello'), ('World'), ('Hi');
-- Insert desired rows into permanent table
INSERT INTO PermanentTable (OtherID, NewString)
WITH OtherSelect AS (
SELECT OtherID AS OtherID FROM OtherTable WHERE OtherName = 'Other Name'
)
SELECT os.OtherID, ns.NewString
FROM OtherSelect os, NewStrings ns;
This way, you only have to define the strings in one place, and you only have to do the query in one place. If you used subqueries like I initially did and like Elendurwen and John suggest, you have to type the subquery into every row. But using temporary tables and a CTE in this way, you can write the query only once.