SQL Migrating old table to new table with an additional column - mysql

So im trying to migrate an old table to a new while maintaining compatibility, so my first guess would be to just map everything over by from example_A to example_B while inserting an old date.
Anyways, my question is there anything else I should do in order to maintain backward compatibility such using relations?
Thank you!
CREATE TABLE example_A
(
id INT
price NUMERIC
primary key (id)
)
CREATE TABLE example_B
(
id INT
price NUMERIC
date DATE
primary key (id, date)
)

Most queries should work compatibly, they'll just ignore the new column. Here are some potential problems:
Queries that use SELECT *. If the query involves a JOIN with another table that has a date column, the date column in the result will be ambiguous as to whether it refers to this table or the other table.
If you join with a table that has a date column, and refer to that column without a table prefix, it will become a syntax error because of the ambiguous reference.
INSERT statements that don't list specific columns will break, because the number of values will no longer match the number of columns.
You should also specify a default value for the new column, so that INSERT queries that don't fill it in will work.

Related

Create a table and specify data types according to an existing query

Let's say I have a table like this
this table is the result of a query from another larger table stored in my database
All I want is to create a table like this one above and specify for each column a custom format and store it into my database
I know that I could do create table mytab as select ... etc
however i don't know how to specify the column formats that I want in mysql
could you please help ?
If you have the query sql, you should be able to do a select into to store the results in a table. Add a LIMIT clause to just store one row. You could then do SHOW CREATE TABLE tablename (from this SO answer) to get the SQL for creating the table. It would be up to you to figure out what your primary key should be.
Assuming with column formats you mean data types: Use CAST to cast to the desired data type.
create new_table as
select
cast( a.metrique as varchar(100) ) as metrique,
cast( b.nombre_de_lignes as int ) as cote_de_lignes, ...
from ...
You may specify columns properties completely or partially. Like there is no SELECT part, and you simply create empty table.
I.e. like
CREATE TABLE table_name ({any definitions allowed in table creation query:
columns specifications, indices, constraints, FKs, etc.})
SELECT ...
In this form each output column in SELECT must have alias which matches according column name defined in CREATE TABLE part. If alias is absent in the structure then a column with the name==alias will be added to the table definition with dynamically formed properties.

extract data from sql, modify it and save the result to a table

This may seem like a dumb question. I am wanting to set up an SQL db with records containing numbers. I would like to run an enquiry to select a group of records, then take the values in that group, do some basic arithmetic on the numbers and then save the results to a different table but still have them linked with a foreign key to the original record. Is that possible to do in SQL without taking the data to another application and then importing it back? If so, what is the basic function/procedure to complete this action?
I'm coming from an excel/macro/basic python background and want to investigate if it's worth the switch to SQL.
PS. I'm wanting to stay open source.
A tiny example using postgresql (9.6)
-- Create tables
CREATE TABLE initialValues(
id serial PRIMARY KEY,
value int
);
CREATE TABLE addOne(
id serial,
id_init_val int REFERENCES initialValues(id),
value int
);
-- Init values
INSERT INTO initialValues(value)
SELECT a.n
FROM generate_series(1, 100) as a(n);
-- Insert values in the second table by selecting the ones from the
-- First one .
WITH init_val as (SELECT i.id,i.value FROM initialValues i)
INSERT INTO addOne(id_init_val,value)
(SELECT id,value+1 FROM init_val);
In MySQL you can use CREATE TABLE ... SELECT (https://dev.mysql.com/doc/refman/8.0/en/create-table-select.html)

Mysql reset number daily

I want to reset number daily,
Table :
CREATE TABLE tickets(
ticketId varchar(10),
moviesname text,
date DATE,
seatnumber INT(5),
PRIMARY KEY(ticketId));
is there anything SQL Syntax to reset the id daily ?
I see 2 possible approaches:
1. Use myisam table's special auto_increment feature:
For MyISAM tables, you can specify AUTO_INCREMENT on a secondary
column in a multiple-column index. In this case, the generated value
for the AUTO_INCREMENT column is calculated as
MAX(auto_increment_column) + 1 WHERE prefix=given-prefix.
Make sure that tickets table is myisam.
tickeid column must be auto_increment
change the primary key to be date, tickeid. The order of the columns is paramount!!!!
2. Spice-up your current max() query to determine the next value
Change the primary key to be date, tickeid. Order of the fields is not important. You cannot leave ticketid to be the pk alone, since you want to restart the numbering daily, which would lead to duplicate index value error message.
Use the following query to get the next ticketid:
select coalesce(max(ticketid),1) from tickets where date=curdate()
The where criteria ensures that every day the ticketid values would restart. The coalesce() is there to assign the number 1 as the first id every day, since max() returns null if there are no records to satisfy the where criteria.
However, the risk with this solution is that multiple statements executed at the same time may yield the same id. Either you handle this situation with proper error handling within your application code (e.g. attempt to insert again), or you serialise the inserts into the tickets table by using explicit locks.

Multiple Column Duplicate Entry Check MySQL

I'm aware that you can create a unique column in your MySQL table, but I'm actually looking to compare TWO columns.
So if I had records like:
Time User Table
10:00pm Fred 29
11:00am Bob 33
I COULD insert a new record with the time 10:00pm and table 33 but not 10:00pm table 29.
I know I could run a query and then nullify my ability to insert a new record if I had results from that query based on comparing those two fields, but I'm wondering if there is a more elegant solution wherein I can get a duplicate entry error from MySQL on the INSERT and save myself a few lines of code.
You can create a unique index that incorporates both columns:
CREATE UNIQUE INDEX idx_time_and_table ON reservations (`Time`, `Table`);
This will block any inserts for the same pairing provided both values are not NULL. Having a NULL value side-steps the unique checking.
You're also using reserved SQL keywords for your column names which you might want to change.
Try using a composite unique constraint across both columns:
ALTER TABLE your_table ADD UNIQUE(`Time`, `Table`);
Now any rows attempting to be added that have matching values will force MySQL to throw an error, which you can test for in your app.
Create an unique index based on the columns you want to be unique:
CREATE UNIQUE INDEX index_name ON table_name ( column1, column2,...);

how to reindex mysql table

I have a table with many rows but they are out of order. Im using the field "id" as the primary key. I also have a "date" field which is a datetime field.
How could i reindex the table so that the entries are id'd in chronological order according to the date field
How about something like a simple query using a variable:
set #ROW = 0;
UPDATE `tbl_example` SET `id` = #ROW := #ROW+1 ORDER BY `fld_date` ASC;
This will order your rows like: 0,1,2,4,5...etc by your date.
the way i would do it is to create a new table with auto increment index and just select all your old table into it ordering by date. you can then remove your old table.
Why do you want the sequence of IDs to correlate with the dates? It sounds like you want to do ORDER BY id and have the rows come back in date order. If you want rows in date order, just use ORDER BY date instead.
Values in an autoincrement ID column should be treated as arbitrary. Relying on your IDs being in date order is a bad idea.
The following SQL snippet should do what you want.
ALTER TABLE test_table ADD COLUMN id2 int unsigned not null;
SET #a:=0;
UPDATE test_table SET id2=#a:=#a+1 ORDER BY `date`;
ALTER TABLE test_table DROP id;
ALTER TABLE test_table CHANGE id2 id int UNSIGNED NOT NULL AUTO_INCREMENT,
ADD PRIMARY KEY (id);
Keep in mind that you can never guarantee the order of an auto-incremented column once you start inserting and removing data, so you shouldn't be relying on any order except that which you specify using ORDER BY in your queries. This is an expensive operation that you are doing, as it requires indexes to be completely re-created, so I wouldn't suggest doing it often.
You can use ALTER TABLE t ORDER BY col;
The allowed syntax of ORDER BY is as in SELECT statements.
I had to do something similar. The best way to do it was the following (you can run it in one SQL Query if you want, but bare in mind that this is a slow and very resource consuming operation):
BE SURE TO MAKE A BACKUP OF YOUR TABLE, INCLUDING STRUCTURE AND DATA BEFORE STARTING THIS QUERY!
ALTER TABLE your_table ADD COLUMN temp_id INT UNSIGNED NOT NULL;
SET #a:=0;
UPDATE your_table SET temp_id=#a:=#a+1 ORDER BY `date` ASC;
ALTER TABLE your_table DROP id;
ALTER TABLE your_table CHANGE temp_id id INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY (id);
ALTER TABLE your_table CHANGE COLUMN id id INT(10) FIRST;
Just don't forget to change "your_table" with the name of your table, and the ORDER BY columns.
Here I explain you what you're doing this way step by step:
First you add a new column named "temp_id" (make sure it's not a name you're using already);
Next you add a temp variable equal to 0 (or to whatever you want for your ID to start from);
Then you update your table, row by row by the set ORDER logic, setting a value for your new column "temp_id" equal to the variable you've set, then increment this variable by 1 (you can do something funky here, for example if you want your ID's to be always even, the you can set #a+2);
Next step you drop (remove) your old column ID;
Then you change the name of your temp_id column back to ID and it as a positive integer with auto increment which is the primary key of your table.
Because ID now is the newly added temp_id column, it's located at the end of your table structure. To move it again as first column, you run the last query, to make sure it's the first column.
If you are using something like phpmysql this could be achieved by:
going to the table (left side list of db's and tables), then
from the options in the upper bar select 'SQL'. Follow the advice by #Ryun, then go to 'Operations' (from the upper bar),
look for 'TABLE OPTIONS', leave everything except 'AUTO_INCREMENT' unchanged,
set the 'AUTO_INCREMENT' value to 1 and press go at the bottom of the form.
What will this do, in all?
It will set the id columns in each from 1 to {count}.
Then it will reset the index of the table so that your next inserted row will equal +1 the number of columns (and not +1 the old index).
#Wyzard made reference to just ordering the columns by date when you retrieve them from the table (and not re-indexing). Since, indeed, the Primary Key should be arbitrary (except to any foreign keys and perhaps the consuming platform (but that is another matter)).