I am trying to copy a table from one database to another database.
Already there are several solutions for this problem. I use this method to solve this problem.
select *
into DbName.dbo.NewTable
from LinkedServer.DbName.dbo.OldTableSourceDB..MySourceTable
I have two databases. One is blog including a table named engineers; another database named msdata including a table named ms. I am trying to copy the table engineers to the database msdata. My query is:
select * into msdata.dbo.ms from linkedserver.blog.dbo.engineers;
but output is
Undeclared variable: msdata
I don't know it is the problem here. Any help will be appreciated.
Just an illustration:
create table so_gibberish.fred1
(
id int auto_increment primary key,
what varchar(40) not null
);
insert so_gibberish.fred1 (what) values ('this'),('that');
insert into newdb789.fred1 select * from so_gibberish.fred1;
-- failed, error code 1146: Table 'newdb789.fred1' doesn't exist
create table newdb789.fred1
(
id int auto_increment primary key,
what varchar(40) not null
);
insert into newdb789.fred1(id,what) select id,what from so_gibberish.fred1;
insert into newdb789.fred1 (what) values ('a new thing');
select * from newdb789.fred1;
+----+-------------+
| id | what |
+----+-------------+
| 1 | this |
| 2 | that |
| 3 | a new thing |
+----+-------------+
good, auto_increment preserved and resumes at 3 for new things
Try this alternative query below, make sure you have already created the table in destination database:
INSERT INTO DestinationDatabase..DestinationTable
SELECT * FROM SourceDatabase..SourceTable;
Related
I'm sorry if it's a silly question, but I don't know how to create dynamically an SQL Table.
Let's imagine that I have two tables :
Table1 : nameT1, numberT1, dateT1
The first one isn't dynamically initiated. BUT the second needs to be, and the values in it have different names. So I started with this approach :
CREATE TABLE Table2 (
nameT2 VARCHAR(20),
numberT2 INTEGER(5),
dateT2 DATETIME
) AS SELECT (
nameT1,
numberT1,
dateT1
) FROM Table1;
But I have some problems with the compilation. And I don't know where I define that (for Table2) :
nameT2 = nameT1
numberT2 = numberT1
dateT2 = dateT1
I simplified the problem, normally I have conditions to select which ones I want to insert from Table1 but that's not part of the problem.
A create as select will create the defined columns then append the selected columns. If you want to rename the columns drop the column definitions and use aliases. For example
DROP TABLE IF EXISTS T,T1;
CREATE TABLE T (nameT1 VARCHAR(3),numberT1 INT, dateT1 DATE);
INSERT INTO T VALUES ('AAA',10,'2020-05-15');
CREATE TABLE T1 AS SELECT
nameT1 AS NAMET2,
numberT1 AS NUMBERT2,
dateT1 AS DATET2
FROM T;
SELECT * FROM T1;
+--------+----------+------------+
| NAMET2 | NUMBERT2 | DATET2 |
+--------+----------+------------+
| AAA | 10 | 2020-05-15 |
+--------+----------+------------+
1 row in set (0.001 sec)
My database structure is like so:
Table 1: customers
| userid | username | password | email |
| 1 | bob | mypassword123 | bob#gmail.com |
Please note that 'userid' is a primary key in this table
Table 2: accountbalance
| userid | balance |
| 1 | 100 |
Please note that 'userid' in accountbalance table is a foreign key to the 'userid' field in customers table.
When a new account is created, I not only want a new row in customers to be created, but I want a corresponding row in accountbalance to be created to give a started value of 100 ($100) but the problem is how do I know what the userid is?
I thought about running a query to look for the id using the username and then doing an INSERT INTO statement in the accountbalance. Would that work? Can I get a general outline?
It depends what db you use. Mysql has LAST_INSERT_INSERT_ID() function which you can call after your insert (just call SELECT LAST_INSERT_INSERT_ID()) and you'll get the id of last inserted row (in case your id is defined as AUTO_INCREMENT). If you use postgres it allows you to perform insert returning id. Something like INSERT INTO customerts(...) VALUES(...) RETURNING userid.
But as you mentioned if your username is unique I would use select using this attribute after insert, because it is db independent.
you can use trigger of mysql
delimiter |
CREATE TRIGGER temp AFTER INSERT ON customers
FOR EACH ROW
BEGIN
INSERT INTO accountbalance SET userid = NEW.userid;
END;
|
delimiter ;
ref: https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html
set default value of balance field in accountbalance table to 100 while creating table or edit later.
The primary key of my table is a char of fixed length 11.
I have precomputed the key in my script, just like this:
SET pes = LPAD(person_number, 11, '0');
Now, my variable meets my critera. It only needs to be added to the database.
INSERT INTO db VALUES(pes, ...);
This is where my problem arises - since the primary key is supposed to be a char, I need to put the value of my variable in single quotes.
However, I don't know how to do that.
I tried to escape them, but
'\''pes'\''
doesn't work.
Is there a simple way to accomplish that?
This should not be a problem !
The mySql varchar data-type should accept numbers!
CREATE TABLE USERS (USER_ID VARCHAR(255) NOT NULL UNIQUE PRIMARY KEY,
USER_NAME VARCHAR(255));
SET #U_ID = LPAD(2018, 11, '0');
INSERT INTO USERS VALUES (#U_ID, 'USER_1'),(2, 'USER_2');
SELECT * FROM USERS;
Will output :
USER_ID | USER_NAME
-------------------------
00000002018 | USER_1
2 | USER_2
This is a working fiddle
You can try to use multi-single-quotes with concat function.
INSERT INTO db VALUES(concat('''', #pes,''''), ...);
Here is a sample
Schema (MySQL v5.7)
CREATE TABLE T(col varchar(50));
SET #pes = '1234';
INSERT INTO T VALUES (concat('''', #pes,''''));
Query #1
select col
FROM T;
| col |
| ------ |
| '1234' |
View on DB Fiddle
TABLE 1
+----+-------+-------+-------+
| uid | color | brand | model |
+----+-------+-------+-------+
| 10 | 1 | 2 | 1 |
+----+-------+-------+-------+
TABLE 2
+----+-------+-------+-------+
| uid | quantity |model |color|
+----+-------+-------+-------+
| 25 | 2 | 2 | 1 |
+----+-------+-------+-------+
I have many tables like this where the uid column is present in every table.I have a value in a variable, say var1=25. I want to check whether var1 value matches with any of the uid value of any table.If it matches I want to print the table name. Can anyone help me with this?
I tried doing this and I found
SELECT `COLUMN_NAME`
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA`='yourdatabasename'
AND `TABLE_NAME`='yourtablename';
But this is not giving what I want since I want to select all the tables in a database irrespective of the table name.If in future any table is added then it should also get selected.
At first, information_schema table doesn't have specific tuple data.
I suggest you to consider different design.
A. Make a meta table and use triggers(attached to base tables) to maintain meta table.
CREATE TABLE meta_table (
id INT AUTO_INCREMENT,
uid INT,
table_name VARCHAR(50)
);
# When you need to add new table (table 3)
CREATE TABLE table_3 (
uid INT,
field1 INT,
field2 INT,
field3
);
DELIMITER $$
CREATE TRIGGER table_3_insert
AFTER INSERT ON table_3
FOR EACH ROW
BEGIN
INSERT INTO meta_table (uid, table_name)
VALUE (NEW.uid, "table_3");
END$$
DELIMITER ;
# If data in `table_3` might be changed or deleted,
# then create trigger for `delete` and `update`
B. Use only one table with unstructured field and parse data field in your application
CREATE TABLE table (
uid INT,
table_type INT,
data VARCHAR(255)
);
INSERT INTO table (10, 1, '{"color":1,"brand":2,"model":1}');
INSERT INTO table (10, 2, '{"quantity":2,"model":2,"color":1}');
As you mentioned "any table can be added" often, I strongly recommend B solution. It is not good design that changing schema(creating table) often.
Lets say I want to store users and groups in a MySQL database. They have a relation n:m. To keep track of all changes each table has an audit table user_journal, group_journal and user_group_journal. MySQL triggers copy the current record to the journal table on each INSERT or UPDATE (DELETES are not supported, because I would need the information which application user has deleted the record--so there is a flag active that will be set to 0 instead of a deletion).
My question/problem is: Assuming I am adding 10 users into a group at once. When I'm later clicking through the history of that group in the user interface of the application I want to see the adding of those 10 users as one step and not as 10 independent steps. Is there a good solution to group such changes together? Maybe it is possible to have a counter that is incremented each time the trigger is ... triggered? I have never worked with triggers.
The best solution would be to put together all changes made within a transaction. So when the user updates the name of the group and adds 10 users in one step (one form controller call) this would be one step in the history. Maybe it is possible to define a random hash or increment a global counter each time a transaction is started and access this value in the trigger?
I don't want to make the table design more complex than having one journal table for each "real" table. I don't want to add a transaction hash into each database table (meaning the "real" tables, not the audit tables--there it would be okay of course). Also I would like to have a solution in the database--not in the application.
I played a bit around and now I found a very good solution:
The Database setup
# First of all I create the database and the basic table:
DROP DATABASE `mytest`;
CREATE DATABASE `mytest`;
USE `mytest`;
CREATE TABLE `test` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`something` VARCHAR(255) NOT NULL
);
# Then I add an audit table to the database:
CREATE TABLE `audit_trail_test` (
`_id` INT PRIMARY KEY AUTO_INCREMENT,
`_revision_id` VARCHAR(255) NOT NULL,
`id` INT NOT NULL,
`something` VARCHAR(255) NOT NULL
);
# I added a field _revision_id to it. This is
# the ID that groups together all changes a
# user made within a request of that web
# application (written in PHP). So we need a
# third table to store the time and the user
# that made the changes of that revision:
CREATE TABLE `audit_trail_revisions` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`user_id` INT NOT NULL,
`time` DATETIME NOT NULL
);
# Now we need a procedure that creates a
# record in the revisions table each time an
# insert or update trigger will be called.
DELIMITER $$
CREATE PROCEDURE create_revision_record()
BEGIN
IF #revision_id IS NULL THEN
INSERT INTO `audit_trail_revisions`
(user_id, `time`)
VALUES
(#user_id, #time);
SET #revision_id = LAST_INSERT_ID();
END IF;
END;
# It checks if a user defined variable
# #revision_id is set and if not it creates
# the row and stores the generated ID (auto
# increment) into that variable.
#
# Next I wrote the two triggers:
CREATE TRIGGER `test_insert` AFTER INSERT ON `test`
FOR EACH ROW BEGIN
CALL create_revision_record();
INSERT INTO `audit_trail_test`
(
id,
something,
_revision_id
)
VALUES
(
NEW.id,
NEW.something,
#revision_id
);
END;
$$
CREATE TRIGGER `test_update` AFTER UPDATE ON `test`
FOR EACH ROW BEGIN
CALL create_revision_record();
INSERT INTO `audit_trail_test`
(
id,
something,
_revision_id
)
VALUES
(
NEW.id,
NEW.something,
#revision_id
);
END;
$$
The application code (PHP)
$iUserId = 42;
$Database = new \mysqli('localhost', 'root', 'root', 'mytest');
if (!$Database->query('SET #user_id = ' . $iUserId . ', #time = NOW()'))
die($Database->error);
if (!$Database->query('INSERT INTO `test` VALUES (NULL, "foo")'))
die($Database->error);
if (!$Database->query('UPDATE `test` SET `something` = "bar"'))
die($Database->error);
// To simulate a second request we close the connection,
// sleep 2 seconds and create a second connection.
$Database->close();
sleep(2);
$Database = new \mysqli('localhost', 'root', 'root', 'mytest');
if (!$Database->query('SET #user_id = ' . $iUserId . ', #time = NOW()'))
die($Database->error);
if (!$Database->query('UPDATE `test` SET `something` = "baz"'))
die($Database->error);
And … the result
mysql> select * from test;
+----+-----------+
| id | something |
+----+-----------+
| 1 | baz |
+----+-----------+
1 row in set (0.00 sec)
mysql> select * from audit_trail_test;
+-----+--------------+----+-----------+
| _id | _revision_id | id | something |
+-----+--------------+----+-----------+
| 1 | 1 | 1 | foo |
| 2 | 1 | 1 | bar |
| 3 | 2 | 1 | baz |
+-----+--------------+----+-----------+
3 rows in set (0.00 sec)
mysql> select * from audit_trail_revisions;
+----+---------+---------------------+
| id | user_id | time |
+----+---------+---------------------+
| 1 | 42 | 2013-02-03 17:13:20 |
| 2 | 42 | 2013-02-03 17:13:22 |
+----+---------+---------------------+
2 rows in set (0.00 sec)
Please let me know if there is a point I missed. I will have to add an action column to the audit tables to be able to record deletions.
Assuming you're rate of adding a batch of users to a group is less than once a second....
I would suggest simply adding a column of type timestamp named something like added_timestamp to the user_group and user_group_journal. DO NOT MAKE THIS AN AUTO UPDATE TIMESTAMP OR DEFAULT IT TO CURRENT_TIMESTAMP, instead, in your code when you insert by batch into the user_group, calculate the current date and time, then manually set this for all the new user_group record.
You may need to tweak your setup to add the field to be copied the rest of the new user_group record into the user_group_journal table.
Then when you could create a query/view that groups on a group_id and the new added_timestamp column.
If more fidelity is needed then 1 second you could use a string column and populate it with a string representation of a more granular time (which you'd need to generate however the libraries your language of use allows).