I have a db in MariaDB 10.1.25 and in this, I have many tables and 20 views.
When I try to backup my db using mysqldump, it works fine for tables but in view definitions, it fails to create a create statement like it does with tables.
The code generated is this:
--
-- Temporary table structure for view `qry_clientes`
--
DROP TABLE IF EXISTS `qry_clientes`;
/*!50001 DROP VIEW IF EXISTS `qry_clientes`*/;
SET #saved_cs_client = ##character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `qry_clientes` (
`Id` tinyint NOT NULL,
`Cliente` tinyint NOT NULL,
`Direccion` tinyint NOT NULL,
`Ciudad` tinyint NOT NULL,
`Fono` tinyint NOT NULL,
`Fax` tinyint NOT NULL,
`Email` tinyint NOT NULL,
`Ruc` tinyint NOT NULL,
`tipo` tinyint NOT NULL
) ENGINE=MyISAM */;
SET character_set_client = #saved_cs_client;
and in this there are no view definitions. I have all the privilegies grandted
Usually, in the mysqldump backup script, the views are first created as tables and then are then dropped at the bottom of the script as each view is being created.
Sometimes there is an error in this process because when a view is created there is a user used as DEFINER. This statement may fail because this user might not exist in the database.
Please verify that the view drop/create script exists at the end, write the error that you are getting (if you are getting) and run the import using the -v option for more logging.
Related
I can get query for creating a specific table via:
SHOW CREATE TABLE `table_name`
If I do this for all of the tables, I can recreate the whole database by running the gathered sql queries. Is there an easier way to get the table creation script, i.e. sql export file, which created the database just by using CREATE statements?
I would solve this with mysqldump. It's a command-line tool that comes with MySQL. Here's the documentation: https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html
You run it at a command prompt, not in phpMyAdmin. You must have access to a shell environment that is either the same host where you run MySQL Server, or at least can reach that host via the network.
For example:
mysqldump --no-data mydatabase mytable
Output is produced:
--
-- Table structure for table `mytable`
--
DROP TABLE IF EXISTS `mytable`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `mytable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL,
`c3` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
(There's more output that I'm omitting.)
You can dump the structure of many tables at once this way, and also views, triggers, procedures, and so on.
If you don't use --no-data, it also includes the data in each table you dump. This makes it an effective tool for data backups. By default, it dumps data in the form of a lot of INSERT statements. So just like the CREATE TABLE statements can recreate the structure of your database if you run them against another MySQL instance, the INSERT statements can recreate your data.
I have the following table structure:
DROP TABLE IF EXISTS `tblusers`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tblusers` (
`UserID` int(5) NOT NULL AUTO_INCREMENT,
`ContactPersonID` int(5) NOT NULL,
`NameOfUser` varchar(70) NOT NULL,
`LegalForm` varchar(70) DEFAULT NULL,
`Address` varchar(70) DEFAULT NULL,
`City` varchar(50) DEFAULT NULL,
`Postal` int(8) DEFAULT NULL,
`Country` varchar(50) DEFAULT NULL,
`VatNum` int(10) DEFAULT NULL,
`Username` varchar(30) NOT NULL,
`Password` varchar(20) NOT NULL,
`Email` varchar(40) NOT NULL,
`Website` varchar(40) DEFAULT NULL,
`IsSeller` bit(1) DEFAULT NULL,
`IsBuyer` bit(1) DEFAULT NULL,
`IsAdmin` bit(1) DEFAULT NULL,
`Description` text,
PRIMARY KEY (`UserID`),
KEY `ContactPersonID` (`ContactPersonID`),
CONSTRAINT `tblusers_tblpersons` FOREIGN KEY (`ContactPersonID`) REFERENCES `tblpersons` (`PersonID`)
) ENGINE=InnoDB AUTO_INCREMENT=87 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = #saved_cs_client */;
Then once I create a user from the UI of my application, I have to manually set the very first admin, and this is the only time I am doing this directly from the DB, all the rest is envisioned to be done from the UI (granting admin privileges):
UPDATE `tblusers` SET `IsAdmin`='1' WHERE `UserID`='79';
but then I get:
Operation failed: There was an error while applying the SQL script to the database.
Executing:
UPDATE `trace`.`tblusers` SET `IsAdmin`='1' WHERE `UserID`='79';
ERROR 1406: 1406: Data too long for column 'IsAdmin' at row 1
SQL Statement:
UPDATE `trace`.`tblusers` SET `IsAdmin`='1' WHERE `UserID`='79'
Which doesn't make sense because I am doing the exact same thing on other machines and it works like a charm. The only difference is that in this scenario I have mysql 5.7 server whereas I have 5.6 versions on the machines that this does work.
I tried the following solution but it didn't work for me. Besides that, the my.ini file is unchanged in the 5.6 machine where it does work.
Downgrading to 5.6 is out of the question. I need a real solution here please.
isadmin is a column of type bit and you are storing a value of type varchar in it which is of larger size than bit. modify query as follows:-
UPDATE `tblusers` SET `IsAdmin`=b'1' WHERE `UserID`='79';
IsAdmin has the datatype of bit(1), yet you are assigning the string '1' to it. Indicate that you are assigning a bit value to it by preceeding the '1' with b or use 0b format:
UPDATE `tblusers` SET `IsAdmin`=b'1' WHERE `UserID`='79';
or
UPDATE `tblusers` SET `IsAdmin`=0b1 WHERE `UserID`='79';
The reason for this behaviour is probably that strict_all_tables or strict_trans_tables setting is enabled on the v5.7 mysql server:
Strict mode controls how MySQL handles invalid or missing values in
data-change statements such as INSERT or UPDATE. A value can be
invalid for several reasons. For example, it might have the wrong data
type for the column, or it might be out of range. A value is missing
when a new row to be inserted does not contain a value for a non-NULL
column that has no explicit DEFAULT clause in its definition. (For a
NULL column, NULL is inserted if the value is missing.) Strict mode
also affects DDL statements such as CREATE TABLE.
The BIT data type is used to store bit values. A type of BIT(M) enables storage of M-bit values. M can range from 1 to 64.
UPDATE tblusers SET IsAdmin=b'1' WHERE UserID='012';
UPDATE tblusers SET IsAdmin=b'0' WHERE UserID='012';
I had the same problem when I synchronized the Model's table from MySQL Workbench to the MySQL server which had old tables with data. the data of old column types is longer than the new column types. (for example: the old column type is char[43] but the new column type is binary[32] so the new column type can't contain all of the old data)
my solution: drop the old table and then synchronized new Model with the old database
I actually have an application based on MySQL with a schema based on InnoDB (with constraints...)
My co-workers need to import this schema, so I export my schema in SQL files.
For example:
DROP TABLE IF EXISTS `admins`;
CREATE TABLE `admins` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(45) NOT NULL,
`password` varchar(45) NOT NULL,
`email` varchar(45) DEFAULT NULL,
`creation_date` datetime NOT NULL,
`close_date` datetime DEFAULT NULL,
`close_reason` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
Now, I would like to have a cross-db application, so:
I tried to import my previous sql files in PostgreSQL, but it didn't work, my SQL files are mysql-related (for example use of ` character...)
I tried to export my schema with mysqldump and a compatibility mode "--compatible=ansi" my goal: have a generic sql file compatible with all major SGBD. But it didn't work: PostgreSQL returns error about synthax
compatible=ansi returns:
DROP TABLE IF EXISTS "admins";
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE "admins" (
"id" smallint(5) unsigned NOT NULL AUTO_INCREMENT,
"username" varchar(45) NOT NULL,
"password" varchar(45) NOT NULL,
"email" varchar(45) DEFAULT NULL,
"creation_date" datetime NOT NULL,
"close_date" datetime DEFAULT NULL,
"close_reason" varchar(45) DEFAULT NULL,
PRIMARY KEY ("id")
);
/*!40101 SET character_set_client = #saved_cs_client */;
I even tried to export with compatibility=postgresql:
DROP TABLE IF EXISTS "admins";
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE "admins" (
"id" smallint(5) unsigned NOT NULL,
"username" varchar(45) NOT NULL,
"password" varchar(45) NOT NULL,
"email" varchar(45) DEFAULT NULL,
"creation_date" datetime NOT NULL,
"close_date" datetime DEFAULT NULL,
"close_reason" varchar(45) DEFAULT NULL,
PRIMARY KEY ("id")
);
/*!40101 SET character_set_client = #saved_cs_client */;
But also didn't work...
I know there are tools to convert MySQL schema to PostgreSQL schema but this isn't the goal...
My question: Is it possible to have only one SQL file compatible with MySQL, PostgreSQL, SQLite... and don't maintain a SQL file for each SGBD ?
Thank you
My question: Is it possible to have only one SQL file compatible with MySQL, PostgreSQL, SQLite... and don't maintain a SQL file for each SGBD ?
Not easily with raw SQL, unless you wish to use a pathetic subset of the databases' supported features.
SELECTs and DML in SQL can be moderately portable, but DDL is generally a hopeless nightmare for all but the total basics. You'll want an abstraction tool that generates the SQL for you, handling database specific differences in sequences/generated keys, type naming, constraints, index creation, etc.
As just one example, lets look at auto-incrementing values / sequences, as frequently used for synthetic keys:
MySQL: integer AUTO_INCREMENT
PostgreSQL: SERIAL (shorthand for a sequence)
MS-SQL: int IDENTITY(1,1)
Oracle (below 12c): No direct support, use a sequence.
Oracle (12c and above): NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY
.. and that's just for the very common task of a generated key. Lots of other fun differences exist. For example, MySQL has tinyint and unsigned int. PostgreSQL does not. PostgreSQL has bool and has bit(n) bitfields, range-types, PostGIS types, etc etc etc which most other DBs don't have. Even for things that're shared, quirks abound - specifying "4 byte signed integer" across all DBs isn't even trivial.
One option to help is Liquibase which I've heard good things about. Some people instead use an ORM to manage their DDL generation instead - though those tend to use, again, only the most primitive of database features.
Background Information
While doing a backup / restore with mysql, I noticed that the restored database was missing a bunch of tables.
Code:
To create the dump file, this is the command that is being used:
mysqldump --databases widgetdb --master-data -u username -ptest --add-drop-database --extended-insert > /var/test/dump.db
Then we are trying to restore the database onto a different server using the following command:
mysql --user=username--password=test widgetdb < /var/test/dbdump.db
So I've checked the dump file and I searched for a table that's missing in the restored database. This is what the code looks like:
DROP TABLE IF EXISTS `widget1`;
/*!50001 DROP VIEW IF EXISTS `widget1`*/;
SET #saved_cs_client = ##character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `widget1` (
`id` tinyint NOT NULL,
`name` tinyint NOT NULL,
`label` tinyint NOT NULL,
`objtype_id` tinyint NOT NULL,
`asset_no` tinyint NOT NULL,
`has_problems` tinyint NOT NULL,
`comment` tinyint NOT NULL
) ENGINE=MyISAM */;
SET character_set_client = #saved_cs_client;
I found the following post: MySQL dump file and commented out lines
This seems to indicate then that the commented out lines will still be run. In my case, I'm running mysql version 5.5.35 which is higher than 50001...
But the table isn't created for me when I restore the dump file.
What I've Tried So Far:
I've tried to change the command use to create the dump file so that I use the --opt option in an attempt to use the "defaults". The restored database is still missing tables.
I have following block of code in MySql:
DROP TABLE IF EXISTS `account.info`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `account.info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`account_id` int(11) NOT NULL,
`year_id` int(11) NOT NULL,
`school_id` int(11) NOT NULL,
PRIMARY KEY (`id`,`account_id`,`year_id`,`school_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7177 DEFAULT CHARSET=utf8;
Its giving me error on first line as:
ERROR 1103 (42000) at line 56: Incorrect table name 'account.info'
What is wrong in it?
Please help me.
From http://dev.mysql.com/doc/refman/5.1/en/identifiers.html:
"Before MySQL 5.1.6, database and table names cannot contain “/”, “\”, “.”, or characters that are not permitted in file names."
Which is why I gave this answer:
You can't use dots in table names. Dots are used to separate database names and table names (and column names). You could try using `account`.`info` if your database name is account and the table name is info. If the table name is supposed to be account.info, you should change that to something else, like account_info. I don't agree with some of the other answers: Quoting never hurts, if done properly.
Since 5.1.6 you can use whatever you please, as shown by #eggyal and others.
As documented under Schema Object Names:
Before MySQL 5.1.6, database and table names cannot contain “/”, “\”, “.”, or characters that are not permitted in file names.
Incidentally, had you wanted to create a table called info within a database called account, then note that as documented under Identifier Qualifiers:
If any components of a multiple-part name require quoting, quote them individually rather than quoting the name as a whole. For example, write `my-table`.`my-column`, not `my-table.my-column`.
try this:
DROP TABLE IF EXISTS account.info;
dont use ` when using dots.
Or quote both db name and table name
DROP TABLE IF EXISTS `account`.`info`;
You seem to want to create and first drop a table in the database account with the name info. If so, do it like this:
DROP TABLE IF EXISTS `account`.`info`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `account`.`info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`account_id` int(11) NOT NULL,
`year_id` int(11) NOT NULL,
`school_id` int(11) NOT NULL,
PRIMARY KEY (`id`,`account_id`,`year_id`,`school_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7177 DEFAULT CHARSET=utf8;
You're specifying a table called account.info and not a table called info in the account db. Quote each part separately:
DROP TABLE IF EXISTS `account`.`info`;
If you are trying to make a table called account.info then older versions of MySQL wont allow a . in a table name.