Looking at examples of a standard SQL layout I see this:
CREATE TABLE IF NOT EXISTS siteUser (
id int(11) AUTO_INCREMENT PRIMARY KEY,
email varchar(64) NOT NULL UNIQUE KEY,
password varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT;
What is th purpose of the "DEFAULT" at the end of specifying the engine? Is there any need for it? I tried to find an explanation of it on tutorial websites but I didn't have any luck.
James
Are you sure it's not an error? I can't find any reference of a default parameter for the database engine in a create table statement. Also, your create table statement fails in SQLFiddle.com in both MySQL 5.1 and 5.5.
I think you might have misinterpreted the default as being part of the engine clause, while actually it was part of a charset or collate clause. For instance, this is valid, since default is an optional keyword in front of the charset clause:
CREATE TABLE IF NOT EXISTS siteUser (
id int(11) AUTO_INCREMENT PRIMARY KEY,
email varchar(64) NOT NULL UNIQUE KEY,
password varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET = utf8;
I guess the charset and collate clauses can have the default keyword (which is practically meaningless by the way), because they specify a default charset or collation, but there is still a possibility to override this per column.
For a storage engine this would be silly. There is no 'default' storage engine for a single table. There is only one. Also, it wouldn't make sense if it would set the default for the whole database. Why would that be an option in a create table statement?
It is used to set ENGINE=InnoDB as the default engine. So one way is to either remove the Engine = INNODB from your create table statement
CREATE TABLE IF NOT EXISTS siteUser (
id int(11) AUTO_INCREMENT PRIMARY KEY,
email varchar(64) NOT NULL UNIQUE KEY,
password varchar(255) NOT NULL
)
DEMO
Or the other way which GolezTrol has suggested:
CREATE TABLE IF NOT EXISTS siteUser (
id int(11) AUTO_INCREMENT PRIMARY KEY,
email varchar(64) NOT NULL UNIQUE KEY,
password varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT charset = utf8;
DEMO
From the Manual: InnoDB as the Default MySQL Storage Engine
In previous versions of MySQL, MyISAM was the default storage engine.
In our experience, most users never changed the default settings. With
MySQL 5.5, InnoDB becomes the default storage engine. Again, we expect
most users will not change the default settings. But, because of
InnoDB, the default settings deliver the benefits users expect from
their RDBMS: ACID Transactions, Referential Integrity, and Crash
Recovery.
However if you want to make the INNODB as your deafult engine then there is one other way:
Under [mysqld] section in your ini file, add:
default-storage-engine = innodb
It is there in /etc/my.cnf
Related
I have a Digital Ocean-managed MySQL database. In order to prevent data replication issues across nodes, DO automatically sets your instance with sql_require_primary_key. This is fine in theory except that there are various WordPress plugins, including notably WP Cerber, which do not support that setting.
I can ask Digital Ocean to disable the setting for me, but I run the risk of my data not replicating properly. So what I'm wondering is, is there a way to disable that setting for specific databases and even tables, or is that setting restricted to the connection settings and the server-wide settings?
The first table on the page you referred is created like this:
CREATE TABLE IF NOT EXISTS cerber_log (
ip varchar(39) CHARACTER SET ascii NOT NULL,
user_login varchar(60) NOT NULL,
user_id bigint(20) unsigned NOT NULL DEFAULT '0',
stamp bigint(20) unsigned NOT NULL,
activity int(10) unsigned NOT NULL DEFAULT '0',
KEY ip (ip)
) DEFAULT CHARSET=utf8;
Adding a primary key:
ALTER TABLE cerber_log ADD COLUMN primaryKey int primary key auto_increment;
You can use any name for the field primaryKey, as long as it is not an existing field.
This should not interfere with the plugin. And if it does than you should probably not (want) to use that plugin at all.
You can temporarily disable it at the session level.
SET SESSION sql_require_primary_key = 0;
I have some migration code that makes primary keys after it makes the table. I added the above snippet to the migration before the table is created. In the end it does make a primary key so all is well.
I am currently using mysql as my database and use flyway to manage database schema. All my unit tests are running against mysql and they are running really slow with adding more unit tests. Now I want to change the database from mysql to h2 memory database in unit tests. Below is my setting for h2 db connection:
#Datasource
spring.datasource.url=jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE;DATABASE_TO_UPPER=true
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.default-transaction-isolation-level=1
When I run flywayMigrate, I got some sql errors. Below is one example, this sql is used to create a table on mysql but failed to run on h2.
CREATE TABLE `file_storage` (
`id` BIGINT(64) NOT NULL AUTO_INCREMENT,
`file_name` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
DEFAULT CHARACTER SET = utf8;
below is the error I got from h2. I don't know what wrong with my sql. Is there a way for h2 to accept mysql database schema?
Execution failed for task ':dbschema:flywayMigrate'.
> Error occurred while executing flywayMigrate
Migration V2016_02_26_12_59__create_file_storage.sql failed
-----------------------------------------------------------
SQL State : 42000
Error Code : 42000
Message : Syntax error in SQL statement "CREATE TABLE ""FILE_STORAGE"" (
""ID"" BIGINT(64) NOT NULL AUTO_INCREMENT,
""FILE_NAME"" VARCHAR(45) NULL,
PRIMARY KEY (""ID""))
DEFAULT CHARACTER[*] SET = UTF8 "; SQL statement:
CREATE TABLE `file_storage` (
`id` BIGINT(64) NOT NULL AUTO_INCREMENT,
`file_name` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
DEFAULT CHARACTER SET = utf8 [42000-190]
Location : db/migration/V2016_02_26_12_59__create_file_storage.sql (/Users/yzzhao/dev/cooltoo/cooltoo_backend/dbschema/build/resources/main/db/migration/V2016_02_26_12_59__create_file_storage.sql)
Line : 1
Statement : CREATE TABLE `file_storage` (
`id` BIGINT(64) NOT NULL AUTO_INCREMENT,
`file_name` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
DEFAULT CHARACTER SET = utf8
Syntax error in SQL statement "CREATE TABLE ""FILE_STORAGE"" (
""ID"" BIGINT(64) NOT NULL AUTO_INCREMENT,
""FILE_NAME"" VARCHAR(45) NULL,
PRIMARY KEY (""ID""))
DEFAULT CHARACTER[*] SET = UTF8 "; SQL statement:
CREATE TABLE `file_storage` (
`id` BIGINT(64) NOT NULL AUTO_INCREMENT,
`file_name` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
DEFAULT CHARACTER SET = utf8 [42000-190]
EDIT
I have hundreds of sql scripts which is running fine in mysql. So I don't want to change anything in these scripts. Is there a way to allow h2 accepts mysql script?
According to this description, you may try to use your H2 database in MySQL Compatibility Mode, by setting it in the connection string as MODE=MySQL. Here is exactly what is said about it:
To use the MySQL mode, use the database URL jdbc:h2:~/test;MODE=MySQL or the SQL statement SET MODE MySQL.
When inserting data, if a column is defined to be NOT NULL and NULL is inserted, then a 0 (or empty string, or the current timestamp for timestamp columns) value is used. Usually, this operation is not allowed and an exception is thrown.
Creating indexes in the CREATE TABLE statement is allowed using INDEX(..) or KEY(..). Example: create table test(id int primary key, name varchar(255), key idx_name(name));
Meta data calls return identifiers in lower case.
When converting a floating point number to an integer, the fractional digits are not truncated, but the value is rounded.
Concatenating NULL with another value results in the other value.
Text comparison in MySQL is case insensitive by default, while in H2 it is case sensitive (as in most other databases). H2 does support case insensitive text comparison, but it needs to be set separately, using SET IGNORECASE TRUE. This affects comparison using =, LIKE, REGEXP.
Your issue can be seen with your example
CREATE TABLE `file_storage`
(
'id` BIGINT(64) NOT NULL AUTO_INCREMENT,
`file_name` VARCHAR(45) NULL,
PRIMARY KEY (`id`)
)
DEFAULT CHARACTER SET = utf8;
The last line "DEFAULT CHARACTER SET = utf8" is setting a mySQL table option. H2 does not have such an option at either the table or schema level as it operates using Unicode at all times.
If you have a lot of SQL DDL statements that have been written over the years for MySQL you are likely to see a lot of such issues.
I am a mysql newbie. I have a question about the right thing to do for create table ddl. Up until now I have just been writing create table ddl like this...
CREATE TABLE file (
file_id mediumint(10) unsigned NOT NULL AUTO_INCREMENT,
filename varchar(100) NOT NULL,
file_notes varchar(100) DEFAULT NULL,
file_size mediumint(10) DEFAULT NULL,
file_type varchar(40) DEFAULT NULL,
file longblob DEFAULT NULL,
CONSTRAINT pk_file PRIMARY KEY (file_id)
);
But I often see people doing their create table ddl like this...
CREATE TABLE IF NOT EXISTS `etags` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`item_code` varchar(100) NOT NULL,
`item_description` varchar(500) NOT NULL,
`btn_type` enum('primary','important','success','default','warning') NOT NULL DEFAULT 'default',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
A few questions...
What difference do the quotes around the table name and column names make?
Is it good practice to explicitly declare the engine and character set? What engine and character sets are used by default?
thanks
There's no difference. Identifiers (table names, column names, et al.) must be enclosed in the backticks if they contain special characters or are reserved words. Otherwise, the backticks are optional.
Yes, it's good practice, for portability to other systems. If you re-create the table, having the storage engine and character set specified explicitly in the CREATE TABLE statement means that your statement won't be dependent on the settings of the default_character_set and default-storage-engine variables (these may get changed, or be set differently on another database.)
You can get your table DDL definition in that same format using the SHOW CREATE TABLE statement, e.g.
SHOW CREATE TABLE `file`
The CREATE TABLE DDL syntax you are seeing posted by other users is typically in the format produced as output of this statement. Note that MySQL doesn't bother with checking whether an identifier contains special characters or reserved words (to see if backticks are required or not), it just goes ahead and wraps all of the identifiers in backticks.
With backticks, reserved words and some special characters can be used in names.
It's simply a safety measure and many tools automatically add these.
The default engine and charset can be set in the servers configuration.
They are often (but not always) set to MyISAM and latin1.
Personally, I would consider it good practice to define engine and charset, just so you can be certain what you end up with.
I have a table inside of my mysql database which I constantly need to alter and insert rows into but it continues running slow when I make changes making it difficult because there are over 200k+ entries. I tested another table which has very few rows and it moves quickly, so it's not the server or database itself but that particular table which has a tough time. I need all of the table's rows and cannot find a solution to get around the load issues.
DROP TABLE IF EXISTS `articles`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `articles` (
`id` int(11) NOT NULL auto_increment,
`content` text NOT NULL,
`author` varchar(255) NOT NULL,
`alias` varchar(255) NOT NULL,
`topic` varchar(255) NOT NULL,
`subtopics` varchar(255) NOT NULL,
`keywords` text NOT NULL,
`submitdate` timestamp NOT NULL default CURRENT_TIMESTAMP,
`date` varchar(255) NOT NULL,
`day` varchar(255) NOT NULL,
`month` varchar(255) NOT NULL,
`year` varchar(255) NOT NULL,
`time` varchar(255) NOT NULL,
`ampm` varchar(255) NOT NULL,
`ip` varchar(255) NOT NULL,
`score_up` int(11) NOT NULL default '0',
`score_down` int(11) NOT NULL default '0',
`total_score` int(11) NOT NULL default '0',
`approved` varchar(255) NOT NULL,
`visible` varchar(255) NOT NULL,
`searchable` varchar(255) NOT NULL,
`addedby` varchar(255) NOT NULL,
`keyword_added` varchar(255) NOT NULL,
`topic_added` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `score_up` (`score_up`),
KEY `score_down` (`score_down`),
FULLTEXT KEY `SEARCH` (`content `),
FULLTEXT KEY `asearch` (`author`),
FULLTEXT KEY `topic` (`topic`),
FULLTEXT KEY `keywords` (`content `,`keywords`,`topic`,`author`),
FULLTEXT KEY `content ` (`content `,`keywords`),
FULLTEXT KEY `new` (`keywords`),
FULLTEXT KEY `author` (`author`)
) ENGINE=MyISAM AUTO_INCREMENT=290823 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = #saved_cs_client */;
With indexes it depends:
more indexes = faster selecting, slower inserting
less indexes = slower selecting, faster inserting
Because the index tables has to be rebuild when inserting and the more data in the table is the more work is for mysql to do to rebuild the index.
So maybe you could remove indexes you not need, that should speed your inserting up.
Another option is to partition you table into many - this stops the bottle neck.
Just try to pass the changes in an update script. This is slow because it creates tables. try updating the tables where changes has been made.
For example create a variable that catches all the changes in the program, with that, insert it to the tables query. That should be fast enough for programs. But as we all know speed depends on how much data is processed.
Let me know if you need anything else.
This may or may not help you directly, but I notice that you have a lot of VARCHAR(255) columns in your table. Some of them seem like they might be totally unnecessary — do you really need all those date / day / month / year / time / ampm columns? — and many could be replaced by more compact datatypes:
Dates could be stored as a DATETIME (or TIMESTAMP).
IP addresses could be stored as INTEGERs, or as BINARY(16) for IPv6.
Instead of storing usernames in the article table, you should create a separate user table and reference it using INTEGER keys.
I don't know what the approved, visible and searchable fields are, but I bet they don't need to be VARCHAR(255)s.
I'd also second Adrian Cornish's suggestion to split your table. In particular, you really want to keep frequently changing and frequently accessed metadata, such as up/down vote scores, separate from rarely changing and infrequently accessed bulk data like article content. See for example http://20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/
"I have a table inside of my mysql database which I constantly need to alter and insert rows into but it continues"
Try innodb on this table if you application performs A LOT update, insert concurrently there, row level locking $$$
I recommend you to split that "big table"(not that big actually, but for MySQL it may be) in several tables to make the most of the query cache. Any time you update some record in that table, the query cache is erased. Also you can try to reduce the isolation level, but that is a little more complicated.
In mysql 5.x Whats the difference if I do something like this:
CREATE TABLE aTable (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
aNumber bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
with this:
CREATE TABLE aTable (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
aNumber bigint(20) DEFAULT NULL
) ENGINE=InnoDB CHARACTER SET=utf8;
Notice I am not specifying the character set as default in the first one. I couldn't find anything in the mysql docs.
The word DEFAULT is optional there - so the two are equivalent, i.e. they set the default character set for the table.
See the MySQL documentation for CREATE TABLE. Here's the relevant bit:
table_option:
ENGINE [=] engine_name
... other options ...
| [DEFAULT] CHARACTER SET [=] charset_name
... more options ...
You can confirm this using the SHOW CREATE TABLE command.
There are 4 levels of default settings in MySQL: server, database, table, and column. Using lower level defaults, you can override higher lever defaults.
If you alter a table that has default charset set to something other than what the database has set, the table default will override the db default.