SQL_MODE and TIME_ZONE when creating DATABASE - mysql

What do these options mean, and what are the possible choices when creating the database?
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
#------------------------------------------------------------
# Script MySQL.
#------------------------------------------------------------
DROP DATABASE if exists BASETEST;
CREATE DATABASE IF NOT EXISTS BASETEST DEFAULT CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI;
USE BASETEST;

SET set's one of MySQL variables. Some of them are system variables some of them are user variables ...
SET SQL_MODE:
SQL_MODE is a system variables and you can see all possible modes in the documentation.
NO_AUTO_VALUE_ON_ZERO :
NO_AUTO_VALUE_ON_ZERO affects handling of AUTO_INCREMENT columns. Normally, you generate the next sequence number for the column by inserting either NULL or 0 into it. NO_AUTO_VALUE_ON_ZERO suppresses this behavior for 0 so that only NULL generates the next sequence number.
SET time_zone :
SET time_zone = "+00:00" Sets the session timezone on UTC.
Read more : How do I set the time zone of MySQL?

The SET statement is used here:
to assign values to variables that affect the operation of the server or clients
Neither the statement nor the variables are specific to database creation. In fact I don't think they should have any noticeable effect:
You cannot configure AUTO_INCREMENT handling in a per database basis (only per server or per session).
A database does not have a time zone (the server or current session do).
It's common though that tools that generate SQL dumps set some variables to configure session and get a predictable environment to run commands. Such variables tend to come from a template and aren't customised for script content.

Related

Setting auto_increment_increment = 1 effect on existing tables

I created a new MySql table and saw that the auto-increment field starts with a value of 3 and increments by 2. I do a SHOW VARIABLES LIKE 'auto_inc%'; and get this-
auto_increment_increment 2
auto_increment_offset 2
I did some research and found that I need to use-
SET ##auto_increment_increment=1; and
SET ##auto_increment_offset=1;
But my question is, will setting both these values to 1 affect how rows are inserted on other tables with auto-increment fields? Will the new rows inserted on those tables start with an auto-increment id of 1 now? Or will this only affect new tables going forward?
The effect of auto_increment_increment and auto_increment_offset is not per-table, it applies to all tables you insert into.
If you use SET in your own session, the variable will be changed in your session only. The behavior in other sessions will not change. Also if you disconnect and reconnect, your session settings are reset to the global settings.
To make the change global, you need to use SET GLOBAL. But the change will be undone the next time MySQL Server restarts.
To make the change global and persistent, either edit the my.cnf file so the variable is set every time MySQL Server starts, or else in MySQL 8.0 they added a feature so you can now use SET PERSIST so you can change global variables and it will retain the setting after a restart.
You can read more about this:
https://dev.mysql.com/doc/refman/8.0/en/using-system-variables.html
https://dev.mysql.com/doc/refman/8.0/en/set-variable.html

Mysql: Not getting an error when updating a NOT NULL column to null

Why does mysql accepts null data when updating a not null column and then converts the data to 0.
I am expecting an error it just does not show up. How can I get an error if someone tries to update a not null column to null? I need it so I can rollback the transaction if I get an error.Is there any configuration needed within the database to do this? Thank you
You've not specified which version of Mysql you're using, and in which mode. I'll answer this assuming you're running Mysql 5.7 without strict mode.
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.
If strict mode is not in effect, MySQL inserts adjusted values for invalid or missing values and produces warnings (see Section 13.7.5.40, “SHOW WARNINGS Syntax”). In strict mode, you can produce this behavior by using INSERT IGNORE or UPDATE IGNORE.
Source: https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sql-mode-full
I recommend you to enable strict mode (STRICT_ALL_TABLES) and fix your application to support it; this will also enforce other query limitations where people are most commonly hit by ONLY_FULL_GROUP_BY.
To set the SQL mode at server startup, use the --sql-mode="modes" option on the command line, or sql-mode="modes" in an option file such as my.cnf (Unix operating systems) or my.ini (Windows). modes is a list of different modes separated by commas. To clear the SQL mode explicitly, set it to an empty string using --sql-mode="" on the command line, or sql-mode="" in an option file.
To change the SQL mode at runtime, set the global or session sql_mode system variable using a SET statement:
SET GLOBAL sql_mode = 'modes';
SET SESSION sql_mode = 'modes';
Source: https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sql-mode-setting
Why does mysql accepts null data when updating a not null column and
then converts the data to 0.
You question is not clear as we need the DDL of the table and the update , but as from what you are saying, Well logically because the column not null has a default value 0. check the below example.
create table Test_table ( name varchar(100) null , position_s varchar(100) default 'Y' not null)
SQL>
Table created
insert into Emp_table (name) values('Me')
SQL>
1 row inserted
SQL>
NAME POSITION_S
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Me Y
#aaron0207 #Moudiz I am using laravel and updates data like this.
$specificReservation = Reservation::where('reference_id',$reference_id)->first();
$specificReservation->res_status = 1;
$specificReservation->payment_id = null;
$specificReservation->save();
I also tried to update manually in the database with this
UPDATE reservations SET payment_id = null
and it also shows no error so I think this is a database problem.

MySQL error: The maximum column size is 767 bytes

When I run a program which does something with MySQL, I got this error message:
2015-06-10 15:41:12,250 ERROR app.wsutils 419 INCRON: Error: ('HY000',
'[HY000] [MySQL][ODBC 5.2(w) Driver][mysqld-5.7.7-rc-log]Index column
size too large. The maximum column size is 767 bytes. (1709)
(SQLExecDirectW)')
I Googled a little bit and found this error might be related to the innodb_large_prefix option. However, I am using MySQL 5.7.7 RC, which has already set innodb_large_prefix to be "ON" (checked in MySQL Workbench), allowing up to 3072 bytes. I am not sure if that is the problem with innodb_large_prefix or not.
Anyway, does anyone have an idea how to fix this problem?
From Wamp Version 3.2.6
Just edit this file:
C:\wamp64\bin\mysql\mysql8.0.27\my.ini
Change the config for innodb-default-row-format value
from innodb-default-row-format=compact
to innodb-default-row-format=dynamic
Restart mysql
With the help of the answer given by BK435, I did the following and solved the problem.
set global innodb_file_format = BARRACUDA;
set global innodb_large_prefix = ON;
create table test (........) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
Your column that you are trying to index is too large and your settings must not be correct for innodb_large_prefix. There are a couple prerequisites parameters that also have to be set in order for innodb_large_prefix to work correctly.
You can check to make sure that innodb_large_prefix is set by running:
show global variables like 'innodb_lar%';
Here are a couple prerequisites for using innodb_large_prefix:
You need to set your global variable innodb_file_format=BARRACUDA
to check settings run: show global variables like 'innodb_fil%';
At the table level you have to use ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED
for Innodb, rows are stored in COMPACT format (ROW_FORMAT=COMPACT) by default.
I was using MariaDB version 10.1.38 and used all of the below given commands but it did not work -
set global innodb_large_prefix = ON;
Query OK, 0 rows affected (0.00 sec)
set global innodb_file_per_table = ON;
Query OK, 0 rows affected (0.00 sec)
set global innodb_file_format = Barracuda;
Query OK, 0 rows affected (0.00 sec)
SET GLOBAL innodb_default_row_format = 'DYNAMIC';
Because after you restart your MySQL (or MariaDB), these settings will not reflect back using the command at the mysql prompt: show variables like 'innodb%';
Then I edited My.ini and added these settings in the file at below location-
C:\xampp\mysql\bin\my.ini
## Innodb settings to bypass error of max size 737
innodb-file-format=barracuda
innodb-file-per-table=ON
innodb-large-prefix=ON
## Above 3 didnot work so i added below
innodb_default_row_format = 'DYNAMIC'
source:https://www.experts-exchange.com/questions/28675824/Why-am-I-unable-to-turn-innodb-large-prefix-ON-successfully-Every-time-I-reboot-mySql-on-my-Ubuntu-VPS-it-resets-to-OFF.html
For me using Mariadb 10.1.31, just add this while you login in Mysql CLI:
SET GLOBAL innodb_file_format = Barracuda;
SET GLOBAL innodb_file_per_table = ON;
SET GLOBAL innodb_large_prefix = ON;
SET GLOBAL innodb_default_row_format = 'DYNAMIC';
Just add the following options to my.cnf
[mysqld]
innodb_file_format=Barracuda
innodb_file_per_table=1
innodb_large_prefix=1
Then, restart mysql server the problem will be resolved.
You need to change the innodb-default-row-format variable to dynamic.
If you are using phpMyAdmin, navigate to variables and search for row format.
If you are using WampServer, navigate to my.ini file like:
C:\wamp64\bin\mysql\mysql8.0.27\my.ini
For more info, visit MySQL Manual
This worked for me:
From Wamp Version 3.2.6
Just edit this file: C:\wamp64\bin\mysql\mysql8.0.27\my.ini
Change the config for innodb-default-row-format value
from innodb-default-row-format=compact
to innodb-default-row-format=dynamic
Restart mysql
Go to mysql config in this file my.cnf
change this line
innodb-default-row-format=compact
to
innodb-default-row-format=dynamic
I had the same error despite having innodb_large_prefix configured correctly.
The issue was in used collation. My db had default collation set to utf8mb4_bin (you can check it in phpmyadmin "Operations" tab for database). It means it uses 4 bytes per char, while utf8 collation (e.g. utf8_unicode_ci) uses 3 bytes per char.
in this case you can either use different collation e.g. by adding DEFAULT CHARSET=utf8 at the end of the CREATE TABLE statement, or limit the index size by using just a part of the column value
like KEY 'identifier' (column1(5),column2(10)).
See also related question: #1071 - Specified key was too long; max key length is 767 bytes
In my case (MySQL version 5.6) the issue was that I was trying to create a table with a column that can have up to 256 characters (the db uses utf8 collation), so 3 bytes per 1 utf8 character = 256*3=768 bytes. The fix was to simply have 255 characters instead of 256.
I could also set innodb_large_prefix, like others suggest, but in my case it was easier to just have fewer symbols.
Just like #sasank-mukkamala said , for me only adding ROW_FORMAT=DYNAMIC to create command did it rightly.
create table `NameOfTheTable` (........) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
Im using Mysql 5.7
Click PHPMyAdmin (home)
Click Variables
On innodb default row formart, click edit then enter 2, then click save
It will show variable value as dynamic
Import table again
I had this problem because I tried to create a String primary key with varchar(254). Easy to overlook sometimes.. So double check your index type and length as well :)
In case someone is working with MySQL 5.6 the only solution that I found was to update to MySQL 5.7 and setting my.cnf as mentioned in previous comments (https://stackoverflow.com/a/57465002/2300390).
I had the same error but on a different issue. I got this error while importing a data (data and schema) script. Deleting the Unique Index fixed the issue for me.
Answer taken from this link
Set the below system variables:
innodb_buffer_pool_size.................................... 702545920
innodb_file_format......................................... Barracuda
innodb_file_format_check................................... ON
innodb_file_format_max..................................... Barracuda
innodb_file_per_table...................................... ON
innodb_large_prefix........................................ ON
innodb_log_file_size....................................... 50331648
Also, make sure when you create your schema you create it as Latin1. That is what finally fixed me.

How to allow empty string for integer in MySQL?

I have integer fields in a table. The POSTs are sent by a complicated JavaScript. They send empty strings like "" but as you guessed MySQL doesn't allow empty strings in integer fields. Are there any options to allow empty strings? Like if it takes an empty string it will save it as NULL.
There are 2 ways to do this.
For Current Mysql Session (Temporary Solution)
First execute query to get current SQL mode of your mysql server.
mysql> SELECT ##sql_mode;
+----------------------------------------------------------------+
| ##sql_mode |
+----------------------------------------------------------------+
|STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+----------------------------------------------------------------+
1 row in set (0.00 sec)
If result contains STRICT_TRANS_TABLES, you have to remove that value to allow insert query to pass NULL value. Make sure your mysql User have privileges to apply this changes and restart Mysql Server after applying this.
SET GLOBAL sql_mode = '';
For Life Time of Mysql (Permanent Solution)
You have to update my.cnf file. Location of that file is : \etc\my.cnf or \etc\mysql\mysql.cnf
There will be some default parameters set under [mysqld] like
[mysqld]
innodb_file_per_table=1
default-storage-engine=MyISAM
performance-schema=0
max_allowed_packet=268435456
open_files_limit=10000
Just add one line under that
sql-mode=""
Make sure to restart Mysql Server after changing this file. Normally root user will be the owner of file so you have to login with root user on server.
For more details to understand what this SQL mode do.
STRICT_TRANS_TABLES
Enable strict SQL mode for transactional storage engines, and when possible for non-transactional storage engines. For details, see Strict SQL Mode.
Refer : http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_strict_trans_tables
NO_AUTO_CREATE_USER
Prevent the GRANT statement from automatically creating new user accounts if it would otherwise do so, unless authentication information is specified. The statement must specify a nonempty password using IDENTIFIED BY or an authentication plugin using IDENTIFIED WITH.
Refer: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_auto_create_user
NO_ENGINE_SUBSTITUTION
Control automatic substitution of the default storage engine when a statement such as CREATE TABLE or ALTER TABLE specifies a storage engine that is disabled or not compiled in.
Refer : http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_engine_substitution
Removing sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" from my.ini has solved the issue.
Edit: Removing the line above works but it is a bad idea. It allows to have things like 0000-00-00 or empty string dates. Better keep the line above and don't insert empty sting into an integer field, instead convert empty string into NULL and then insert that NULL into integer field.
Assuming that the column allows for NULL values, you must explicitly tell MySQL to use a value of NULL, rather than passing an empty string (which is cast to 0):
INSERT INTO table (column_name) VALUES (NULL);

MySQL replication: temporarily prevent specific SQL statements replicating to the slaves?

I want to connect and execute one (or sometimes several) SQL statements, and NOT have those replicated to the slaves.
I have no replicate-do or replicate-ignore configs, so I can't use some non-replicated database to send the commands from. And I know about:
set global sql_slave_skip_counter = 1
But that's on the slave. I'd like to be able to run a similar command on the master and have the following N commands not sent out to the slaves (which I guess means not logged in the binlogs, either).
SET sql_log_bin=0 is what you're looking for. Requires SUPER priv., and will turn off logging of commands from your session until you set it back to 1. See http://dev.mysql.com/doc/refman/5.0/en/server-session-variables.html#sysvar_sql_log_bin
SET sql_log_bin=0;
UPDATE ... ;
INSERT ... ;
DELETE ... ;
SET sql_log_bin=1 ;
BE CAREFUL.....!
SET sql_log_bin=0;
Master MySQL server automatically set this 0 value to 1 after a while(after about one minute). It does not wait until we explicitly set it to 1. So according to my experience this not a safe way to turn off binary logging at all.....!