Getting SHOW CREATE TABLE from a view, as if it were a table - mysql

I have access to a remote database, and I would like to dump the schema and data of several views onto my local machine and load this into my local database as tables in a quick and easy way.
I lack the user privileges to run CREATE TABLE AS (SELECT * FROM target_view), otherwise this would be trivial to solve. In other words, I want to retrieve and recreate the "composite" schema of target_view as if it were a table.
I do not want the output of SHOW CREATE VIEW, as this only shows a complex SELECT statement with joins to various tables on remote I have limited ability to access. And a problem I'm seeing in MySQL 8.x is when I run SHOW CREATE TABLE on the view, this command simply acts as an alias of SHOW CREATE VIEW (which is reasonable).
Frustratingly, I can run DESCRIBE and see the schema of these views as they were tables. I really just need to convert this information into a CREATE TABLE statement without actually being able to run CREATE TABLE.
In case it weren't obvious, the key is to avoid manual reconstruction of these views' tabular schemas (as they may change in the future). I also want to avoid the solution of reverse engineering a generic table construction of 20-30 generic VARCHAR or TEXT columns from a CSV dump.

I don't know of any way to display the metadata of a result set in CREATE TABLE syntax.
What I would do given your circumstance is first create on your local MySQL instance the base table and the view, then you can use the CREATE TABLE AS SELECT ... syntax to produce a concrete table to match the metadata of the view result set.

Related

Save MySql 'Show' result in db

So I'm kind of stumped.
I have a MySql project that involves a database table that is being manipulated and altered by scripts on a regular basis. This isn't so unusual, but I need to automate a script to run (after hours, when changes aren't happening) that would save the result of the following:
SHOW CREATE TABLE [table-name];
This command generates the ready-to-run script that would create the (empty) table in it's current state.
In SqlWorkbench and Navicat it displays the result of this SHOW command in a field in a result set, as if it was the result of a SELECT statement.
Ideally, I want to take into a variable in a procedure, and change the table name; adding a '-mm-dd-yyyy' to end of it, so I could show the day-to-day changes in the table schema on an active server.
However, I can't seem to be able to do that. Unlike a Select result set, I can't use it like that. I can't get it in a variable, or save it to a temporary, or physical table or anything. I even tried to return this as a value in a function, from which I got the error that a function cannot return a result set - which explains why it's displayed like one in the db clients.
I suspect that this is a security thing in MySql? If so, I can totally understand why and see the dangers exposed to a hacker, but this isn't a public-facing box at all, and I have full root/admin access to it. Hopefully somebody has already tackled this problem before.
This is on MySql 8, btw.
[Edit] After my first initial comments, I need to add; I'm not concerned about the data with this question whatsoever, but rather just these schema changes.
What I'd really -like- to do is this:
SELECT `Create Table` FROM ( SHOW CREATE TABLE carts )
But this seems to be mixing apples and oranges, as SHOW and SELECT aren't created equal, although they both seem to return the same sort of object
You cannot do it in the MySQL stored procedure language.
https://dev.mysql.com/doc/refman/8.0/en/show.html says:
Many MySQL APIs (such as PHP) enable you to treat the result returned from a SHOW statement as you would a result set from a SELECT; see Chapter 29, Connectors and APIs, or your API documentation for more information. In addition, you can work in SQL with results from queries on tables in the INFORMATION_SCHEMA database, which you cannot easily do with results from SHOW statements. See Chapter 26, INFORMATION_SCHEMA Tables.
What is absent from this paragraph is any mention of treating the results of SHOW commands like the results of SELECT queries in other contexts. There is no support for setting a variable to the result of a SHOW command, or using INTO, or running SHOW in a subquery.
So you can capture the result returned by a SHOW command in a client programming language (Java, Python, PHP, etc.), and I suggest you do this.
In theory, all the information used by SHOW CREATE TABLE is accessible in the INFORMATION_SCHEMA tables (mostly TABLES and COLUMNS), but formatting a complete CREATE TABLE statement is a non-trivial exercise, and I wouldn't attempt it. For one thing, there are new features in every release of MySQL, e.g. new data types and table options, etc. So even if you could come up with the right query to produce this output, in a couple of years it would be out of date and it would be a thankless code maintenance chore to update it.
The closest solution I can think of, in pure MySQL, is to regularly clone the table structure (no data), like so:
CREATE TABLE backup_20220618 LIKE my_table;
As far as I know, to get your hands on the full explicit CREATE TABLE statement, as a string, would require the use of an external tool like mysqldump which was designed specifically for that purpose.

Access query runs on table that does not exist in database

I would like to recreate a few existing Access queries in a new database so that I can tweak them a bit. The problem I am running into is that some of the tables being queried do not seem to exist in the current database. These tables all end with a 1.
For example, INV_MTL_ITEM_LOCATIONS is an imported table in the database, but
INV_MTL_ITEM_LOCATIONS_1 is being queried even though it does not show up in the tables panel on the left.
Is this some type of duplication functionality that I am not aware of? The query runs without any errors.
No, the query runs on an aliased table. It's actually just querying INV_MTL_ITEM_LOCATIONS
Using SQL, you can create an alias for a table. This is especially useful when querying the same table twice in one query, but also commonly used to shorten queries.
Your query will probably look something like this:
SELECT something
FROM INV_MTL_ITEM_LOCATIONS AS INV_MTL_ITEM_LOCATIONS_1
Access automatically creates these aliases when using the query builder and if you add the same table more than once. When removing the non-aliased table, the other one stays aliased.
This is entirely normal, and as far as I know, never a problem.
Erik's answer explains it perfectly.
But to be exhaustive, you CAN actually create a query on a table that is NOT in the current database (nor a linked table).
Here is an example:
SELECT *
FROM History IN 'c:\test\mySecretBackend.accdb'
You can also create that in design view, just by
setting the query's Source Database property to c:\test\mySecretBackend.accdb
click on Show table

Mysql views return data when table empty

I am having a weird problem with mysql. I am developing a visual application on C# that stores data into a database. Previously I used SQL for the Database, but my client changed his mind for mysql. So I recreated the same schema on mysql. Now it is happening a really odd thing: My tables are completely empty, but when I execute the views, they return me back data from the old SQL tables, when I read directly from the tables they appear empty. The user that I use to connect are different and the most strange thing is that it happens even when I execute the view on mysql workbench. I have even truncated the tables in mysql and still the same thing. Does anybody know what may cause this anomaly and how to solve it?
p.s. Workbench version 6.2; Sql version SQL SERVER 2014
Regards.
In MySQL, a view is a virtual table based on the result-set of an SQL statement.
It contains rows and columns, just like a real table in your database. The fields in a view are fields from one or more real tables in the database.
When you execute the views, they return back data from the old SQL tables. It is because your view still contains the data you run a while ago. You have forgotten to Drop your View every time you execute it. To Drop a MySQL view, try this one:
DROP VIEW view_name
Views do NOT contain data of any kind -- except for Materialized Views and MySQL does not have those. If views had to be dropped and recreated every time a DML statement was executed on a table, views would be utterly useless.
The only time a view can return old data is when one process changes the contents of a table used in the view and the view is queried by another process before the first process commits the changes. You have not specified how the tables are being changed and how they are being queried. Nor have you included the create view statement. You could well be using other tables than what you think. This can happen during initial design of a database if tables are being slapped around like mad.

How to accomplish "MySQL cross database reference" with PostgreSQL

We will migrate the database from mysql to postgresql in our product(through java). So we need to change the mysql query to postgresql query in java application. How to create the table i.e., databasename.tablename in postgresql.
For mysql, we can directly create the table e.g create table information.employee.
Here database name is "information" and table name is "employee" . Is it possible to achieve same query in postgresql.
I searched google it says cross database reference is not possible. Please help me.
I saw pg_class table it contains the table names in the specific database, like wise databse and tables relationships are stored in any other table.
This is normally done using schemas rather than databases, which is more or less like how MySQL organizes it anyway.
Instead of
create database xyz
use
create schema xyz
When you create tables, create them:
create table xyz.myTable
you will need to update your search path to see them on the psql command line tool, or if you want to query them without using the schema explicitly. The default schema is public, so when you create a table without a schema name, it ends up in public. If you modify your search_path as below, the default schema becomes the first in the list: xyz.
set search_path=xyz,public,pg_catalog;
and you must not have spaces in that statement. You can do it globally for a user/role too:
alter role webuser set search_path=xyz,public,pg_catalog;
Also, don't forget that postgresql string matches are case sensitive by default (this one catches people out a lot).
If you want to have different physical locations for the files for each schema, you can do that with tablespaces. If you have a look at the postgresql documentation page, they have info on how to do it, it's pretty easy.
database in MySQL == schema in PostgreSQL. So you will most probably want to migrate all your mysql dbs into one postgres db. Then you will be able to do "cross-database" queries.
See my answer to this question: Relationship between catalog, schema, user, and database instance

Setting up a master database to control the structure of other databases

I got a case where I have several databases running on the same server. There's one database for each client (company1, company2 etc). The structure of each of these databases should be identical with the same tables etc, but the data contained in each db will be different.
What I want to do is keep a master db that will contain no data, but manage the structure of all the other databases, meaning if I add, remove or alter any tables in the master db the changes will also be mirrored out to the other databases.
Example: If a table named Table1 is created in the master DB, the other databases (company1, company2 etc) will also get a table1.
Currently it is done by a script that monitors the database logs for changes made to the master database and running the same queries on each of the other databases. Looked into database replication, but from what I understand this will also bring along the data from the master database, which is not an option in this case.
Can I use some kind of logic against database schemas to do it?
So basicly what I'm asking here is:
How do I make this sync happen in the best possible way? Should I use a script monitoring the logs for changes or some other method?
How do I avoid existing data getting corrupted if a table is altered? (data getting removed if a table is dropped is okay)
Is syncing from a master database considered a good way to do what I wish (having an easy maintainable structure across several datbases)?
How will making updates like this affect the performance of the databases?
Hope my question was clear and that this is not a duplicate of some other thread. If more information and/or a better explantion of my problem is needed, let me know:)
You can get the list of tables for a given schema using:
select TABLE_NAME from information_schema.tables where TABLE_SCHEMA='<master table name>';
Use this list for a script or stored procedure ala:
create database if not exists <name>;
use <name>;
for each ( table_name in list )
create table if not exists <name>.table_name like <master_table>.table_name;
Now that Im thinking about it you might be able to put a trigger on the 'information_schema.tables' db that would call the 'create/maintain' script. Look for inserts and react accordingly.