Mysql Select row, update values and insert into another table - mysql

I have a temporary table with some rows:
$query = "CREATE TEMPORARY TABLE {$tn} (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(255) NOT NULL,
`title` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB";
I would like to select each row in this table, nulify id, update 'type' (for example) and insert whole selected row into another table (which has the same columns as this table).
I tried this but I am getting an error near SET ( You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SET )
foreach ($ids as $id) {//this is each id in temp table
$query = "INSERT INTO $another_table
SELECT * FROM {$tn} WHERE id='$id'
SET id=NULL, type='foo'";
$result = $conn->query($query) or die(mysqli_error($conn));
}

I am not a PHP guru, but this is the syntax you should be following. You may select any number of constants you wish from a table.
INSERT INTO $another_table (id, type, title)
SELECT NULL, 'foo', title
FROM {$tn}
WHERE id = '$id';
This assumes that the other destination table uses the same name for its columns as your first table. If not, then you will have to change the first line of my query.
Note that you should ideally be using a prepared statement here.

If both your tables have the SAME amount of columns, with the same order, and you want to avoid listing each and every column, You could just copy the entry and updated the changed value within the same transaction:
START TRANSACTION;
INSERT INTO table2 SELECT * FROM table1 WHERE id = 57;
UPDATE table2 SET columnYouWantToChange="New Value" WHERE id = 57;
COMMIT;
But maybe you should OUTLINE, what you are trying to achieve? having 2 tables with identical columns "smells" like bad design. Maybe you'd better use the same table along with revision numbers of your data row?

Your SQL is not valid, You have an insert statement with a set statement in it.
All you need is a basic INSERT SELECT this is also no need for the for loop.
INSERT INTO $another_table (id, type, title)
SELECT id, 'foo', title
FROM {$tn}
You can do the set statement as an update after inserting all rows if that is easier to get you head around.
UPDATE $another_table SET id = NULL
https://dev.mysql.com/doc/refman/8.0/en/insert-select.html

FYI if you want SET many or all the columns from a table with the same column names this query run on information_schema will generate the most tedious part of the code for you:
select concat('target.', column_name ,' = ','source.', column_name ,', ') as line
from `columns`
where `columns`.table_name = 'target';

Related

Adding entry inside a table in database

I wanted to add an entry inside a table in SQL database.
For example I have the following Database
CREATE TABLE `distributor_geneology` (
`distributor_gen_id` bigint(20) NOT NULL,
`user_id` varchar(24) NOT NULL,
`id` bigint(20) NOT NULL,
`sponsor_id` bigint(20) NOT NULL,
`rank` tinyint(4) NOT NULL
);
And I want to add an entry in sponsor_id or say id inside a database.
First, I imported the database in my SQL Workbench then In my SQL Workbench, I ran a command select * from distributor_geneology which gave me
Error Code: 1146. Table 'dba_db.distributor_genelogy' doesn't exist
[Question] How can I create/add Entry for ID (or sponsor ID or any other filed)?
One typical way which data would enter a MySQL database is via an INSERT statement:
INSERT INTO distributor_geneology (distributor_gen_id, user_id, id, sponsor_id, rank)
VALUES
(1, 1, 1, 1, 1);
I am inserting 1 everywhere, but you may alter the tuple with the values you want.
Another way to get data into a table is bulk loading via LOAD DATA.
For your first part of your question which is "Add an entry to inside table"
this operation called insertion in the database and the keyword database used to insert data is insert into
It is possible to write the INSERT INTO statement in two ways:
1- specifies both the column names and the values to be inserted
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
you can rearrange the columns orders as you want but must the values be the same order of the columns and you can let any column null if you don't want to insert any data in this column but be careful if you have not null column you must insert in you query
in your case, all the columns you have are not null.
2- if you do not need to specify the column names in the SQL query. make sure the order of the values is in the same order as the columns in the table
INSERT INTO table_name
VALUES (value1, value2, value3, ...);
For your second part of your question which is "Error Code: 1146. Table 'dba_db.distributor_genelogy' doesn't exist"
First, ensure you imported the DB correctly and if yes > write try to use DB name in your query.
select * from DB_Name.Table_Name
Edit:
Try this query format
INSERT INTO distributor_geneology (distributor_gen_id, user_id, id, sponsor_id, rank)
VALUES
(10, '10', 10, 10, 10);
please note I put second value between 2 quotes because you are defining the user_id as varchar which means not an integer so we should put it between qouts

Why is this MySQL query causing an error?

Query:
INSERT INTO `metadata` (`group_id`, `key`, `value`)
VALUES ("19", "originality", "2")
ON DUPLICATE KEY UPDATE (`group_id` = `19`, `key`=`originality`, `value`=`2`)
The table:
group_id | key | value
----------------------------------------
group_id and key both have a UNIQUE index.
The error happens when I try to run the query when a row already exists with the id 19. The way I want the query to function is, if there is no row with that id, insert it and if there is update it instead of inserting a new row.
The error message I get is the typical:
I'm not sure if a ( should follow the UPDATE keyword - I think not. So try
ON DUPLICATE KEY UPDATE `group_id` = 19, `key`='originality', `value`=2
(or replace group_id with submission_group_id - your error message doesn't seem to match the original query)
you can only use ` on table columns and table names, not for data.
data should use ' or "
like:
ON DUPLICATE KEY UPDATE `group_id` = 19, `key`="originality", `value`=2
The quote tag must be the ' character not the ` character.
if there is no row with that id, insert it and if there is update it instead of inserting a new row.
If you want to do this you should try statement like:
IF EXISTS (SELECT * FROM sometable WHERE ColumnName='somevalue')
UPDATE sometable SET (...) WHERE ColumnName='somevalue'
ELSE
INSERT INTO Table1 VALUES (...)

How to get the next auto-increment id in mysql

How to get the next id in mysql to insert it in the table
INSERT INTO payments (date, item, method, payment_code)
VALUES (NOW(), '1 Month', 'paypal', CONCAT("sahf4d2fdd45", id))
You can use
SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'table_name'
AND table_schema = DATABASE( ) ;
or if you do not wish to use information_schema you can use this
SHOW TABLE STATUS LIKE 'table_name'
You can get the next auto-increment value by doing:
SHOW TABLE STATUS FROM tablename LIKE Auto_increment
/*or*/
SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = 'tablename'
Note that you should not use this to alter the table, use an auto_increment column to do that automatically instead.
The problem is that last_insert_id() is retrospective and can thus be guaranteed within the current connection.
This baby is prospective and is therefore not unique per connection and cannot be relied upon.
Only in a single connection database would it work, but single connection databases today have a habit of becoming multiple connection databases tomorrow.
See: SHOW TABLE STATUS
This will return auto increment value for the MySQL database and I didn't check with other databases. Please note that if you are using any other database, the query syntax may be different.
SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'your_table_name'
and table_schema = 'your_database_name';
SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'your_table_name'
and table_schema = database();
The top answer uses PHP MySQL_ for a solution, thought I would share an updated PHP MySQLi_ solution for achieving this. There is no error output in this exmaple!
$db = new mysqli('localhost', 'user', 'pass', 'database');
$sql = "SHOW TABLE STATUS LIKE 'table'";
$result=$db->query($sql);
$row = $result->fetch_assoc();
echo $row['Auto_increment'];
Kicks out the next Auto increment coming up in a table.
In PHP you can try this:
$query = mysql_query("SELECT MAX(id) FROM `your_table_name`");
$results = mysql_fetch_array($query);
$cur_auto_id = $results['MAX(id)'] + 1;
OR
$result = mysql_query("SHOW TABLE STATUS WHERE `Name` = 'your_table_name'");
$data = mysql_fetch_assoc($result);
$next_increment = $data['Auto_increment'];
Use LAST_INSERT_ID() from your SQL query.
Or
You can also use mysql_insert_id() to get it using PHP.
Solution:
CREATE TRIGGER `IdTrigger` BEFORE INSERT ON `payments`
FOR EACH ROW
BEGIN
SELECT AUTO_INCREMENT Into #xId
FROM information_schema.tables
WHERE
Table_SCHEMA ="DataBaseName" AND
table_name = "payments";
SET NEW.`payment_code` = CONCAT("sahf4d2fdd45",#xId);
END;
"DataBaseName" is the name of our Data Base
Simple query would do
SHOW TABLE STATUS LIKE 'table_name'
For MySQL 8 use SHOW CREATE TABLE to retrieve the next autoincrement insert id:
SHOW CREATE TABLE mysql.time_zone
Result:
CREATE TABLE `time_zone` (
`Time_zone_id` int unsigned NOT NULL AUTO_INCREMENT,
`Use_leap_seconds` enum('Y','N') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
PRIMARY KEY (`Time_zone_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1784 DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 ROW_FORMAT=DYNAMIC COMMENT='Time zones'
See the AUTO_INCREMENT=1784 at the last line of returned query.
Compare with the last value inserted:
select max(Time_zone_id) from mysql.time_zone
Result:
+-------------------+
| max(Time_zone_id) |
+-------------------+
| 1783 |
+-------------------+
Tested on MySQL v8.0.20.
SELECT id FROM `table` ORDER BY id DESC LIMIT 1
Although I doubt in its productiveness but it's 100% reliable
You have to connect to MySQL and select a database before you can do this
$table_name = "myTable";
$query = mysql_query("SHOW TABLE STATUS WHERE name='$table_name'");
$row = mysql_fetch_array($query);
$next_inc_value = $row["AUTO_INCREMENT"];
I suggest to rethink what you are doing. I never experienced one single use case where that special knowledge is required. The next id is a very special implementation detail and I wouldn't count on getting it is ACID safe.
Make one simple transaction which updates your inserted row with the last id:
BEGIN;
INSERT INTO payments (date, item, method)
VALUES (NOW(), '1 Month', 'paypal');
UPDATE payments SET payment_code = CONCAT("sahf4d2fdd45", LAST_INSERT_ID())
WHERE id = LAST_INSERT_ID();
COMMIT;
You can't use the ID while inserting, neither do you need it. MySQL does not even know the ID when you are inserting that record. You could just save "sahf4d2fdd45" in the payment_code table and use id and payment_code later on.
If you really need your payment_code to have the ID in it then UPDATE the row after the insert to add the ID.
What do you need the next incremental ID for?
MySQL only allows one auto-increment field per table and it must also be the primary key to guarantee uniqueness.
Note that when you get the next insert ID it may not be available when you use it since the value you have is only within the scope of that transaction. Therefore depending on the load on your database, that value may be already used by the time the next request comes in.
I would suggest that you review your design to ensure that you do not need to know which auto-increment value to assign next
use "mysql_insert_id()". mysql_insert_id() acts on the last performed query, be sure to call mysql_insert_id() immediately after the query that generates the value.
Below are the example of use:
<?php
$link = mysql_connect('localhost', 'username', 'password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');
mysql_query("INSERT INTO mytable VALUES('','value')");
printf("Last inserted record has id %d\n", mysql_insert_id());
?>
I hope above example is useful.
If return no correct AUTO_INCREMENT, try it:
ANALYZE TABLE `my_table`;
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE (TABLE_NAME = 'my_table');
This clear cache for table, in BD
using the answer of ravi404:
CREATE FUNCTION `getAutoincrementalNextVal`(`TableName` VARCHAR(50))
RETURNS BIGINT
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE Value BIGINT;
SELECT
AUTO_INCREMENT INTO Value
FROM
information_schema.tables
WHERE
table_name = TableName AND
table_schema = DATABASE();
RETURN Value;
END
using in your insert query, to create a SHA1 Hash. ex.:
INSERT INTO
document (Code, Title, Body)
VALUES (
sha1( getAutoincrementalNextval ('document') ),
'Title',
'Body'
);
Improvement of #ravi404, in case your autoincrement offset IS NOT 1 :
SELECT (`auto_increment`-1) + IFNULL(##auto_increment_offset,1)
FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = your_table_name
AND table_schema = DATABASE( );
(auto_increment-1) : db engine seems to alwaus consider an offset of 1. So you need to ditch this assumption, then add the optional value of ##auto_increment_offset, or default to 1 : IFNULL(##auto_increment_offset,1)
For me it works, and looks simple:
$auto_inc_db = mysql_query("SELECT * FROM my_table_name ORDER BY id ASC ");
while($auto_inc_result = mysql_fetch_array($auto_inc_db))
{
$last_id = $auto_inc_result['id'];
}
$next_id = ($last_id+1);
echo $next_id;//this is the new id, if auto increment is on
SELECT AUTO_INCREMENT AS next_id FROM information_schema.tables WHERE table_name = 'table name' AND table_schema = 'database name of table name'
mysql_insert_id();
That's it :)

Copying rows in MySQL

I want to copy all of the columns of a row, but not have to specify every column. I am aware of the syntax at http://dev.mysql.com/doc/refman/5.1/en/insert-select.html but I see no way to ignore a column.
For my example, I am trying to copy all the columns of a row to a new row, except for the primary key.
Is there a way to do that without having to write the query with every field in it?
If your id or primary key column is an auto_increment you can use a temp table:
CREATE TEMPORARY TABLE temp_table
AS
SELECT * FROM source_table WHERE id='7';
UPDATE temp_table SET id='100' WHERE id='7';
INSERT INTO source_table SELECT * FROM temp_table;
DROP TEMPORARY TABLE temp_table;
so in this way you can copy all data in row id='7' and then assign
new value '100' (or whatever value falls above the range of your current auto_increment value in source_table).
Edit: Mind the ; after the statments :)
You'll need to list out the columns that you want to select if you aren't selecting them all. Copy/Paste is your friend.
This is a PHP script that I wrote to do this, it will assume that your first col is your auto increment.
$sql = "SELECT * FROM table_name LIMIT 1";
$res = mysql_query($sql) or die(mysql_error());
for ($i = 1; $i < mysql_num_fields($res); $i++) {
$col_names .= mysql_field_name($res, $i).", ";
}
$col_names = substr($col_names, 0, -2);
$sql = "INSERT INTO table_name (".$col_names.") SELECT ".$col_names." FROM table_name WHERE condition ";
$res = mysql_query($sql) or die(mysql_error());
If you don't specify the columns you have to keep the entries in order. For example:
INSERT INTO `users` (`ID`, `Email`, `UserName`) VALUES
(1, 'so#so.com', 'StackOverflow')
Would work but
INSERT INTO `users` VALUES
('so#so.com', 'StackOverflow')
would place the Email at the ID column so it's no good.
Try writing the columns once like:
INSERT INTO `users` (`Email`, `UserName`) VALUES
('so#so.com', 'StackOverflow'),
('so2#so.com', 'StackOverflow2'),
('so3#so.com', 'StackOverflow3'),
etc...
I think there's a limit to how many rows you can insert with that method though.
No, this isn't possible.
But it's easy to get the column list and just delete which one you don't want copied this process can also be done through code etc.
Copy the table to a new one, then delete the column you don't want. Simple.
I'm assuming that since you want to omit the primary key that it is an auto_increment column and you want MySQL to autogenerate the next value in the sequence.
Given that, assuming that you do not need to do bulk inserts via the insert into ... select from method, the following will work for single/multi record inserts:
insert into mytable (null, 'a', 'b', 'c');
Where the first column is your auto_incremented primary key and the others are your other columns on the table. When MySQL sees a null (or 0) for an auto_incremented column it will automatically replace the null with the next valid value (see this link for more information). This functionality can be disabled by disabling the NO_AUTO_VALUE_ON_ZERO sql mode described in that link.
Let me know if you have any questions.
-Dipin

SQL - How to make a conditional INSERT

Using only MySQL, I'm seeing if it's possible run an insert statement ONLY if the table is new. I successfully created a user variable to see if the table exists. The problem is that you can't use "WHERE" along with an insert statement. Any ideas on how to get this working?
// See if the "country" table exists -- saving the result to a variable
SELECT
#table_exists := COUNT(*)
FROM
information_schema.TABLES
WHERE
TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'country';
// Create the table if it doesn't exist
CREATE TABLE IF NOT EXISTS country (
id INT unsigned auto_increment primary key,
name VARCHAR(64)
);
// Insert data into the table if #table_exists > 0
INSERT INTO country (name) VALUES ('Afghanistan'),('Aland Islands') WHERE 0 < #table_exists;
IF #TableExists > 0 THEN
BEGIN
INSERT INTO country (name) VALUES ('Afghanistan'),('Aland Islands');
END
Use an if statement instead of the where clause:
http://dev.mysql.com/doc/refman/5.0/en/if-statement.html