How to make sure that the column value is always added in Uppercase? - mysql

I have an existing column host and want to make sure that the column value host is always added in Uppercase.
I am using Alter Table command as below:
ALTER TABLE `mydb`.`myTable`
CHANGE COLUMN `host` `host`
VARCHAR(255) GENERATED ALWAYS AS (UPPER()) STORED;
This is causing an error and I am not able to alter the column.
Operation failed: There was an error while applying the SQL script to the database.
ERROR 1582: Incorrect parameter count in the call to native function 'UPPER'
SQL Statement:
ALTER TABLE mydb.myTable
CHANGE COLUMN host host VARCHAR(255) GENERATED ALWAYS AS (UPPER()) VIRTUAL
I want to make sure that moving forward the value inserted in host is always in uppercase.
I want to achieve this by updating the value in uppercase at runtime.
I don't want to add any constraint as it will cause an error when the host value is entered in lowercase.

It is not entirely clear what you are trying to do.
If you want to set a constraint on the table that allows only upper case letters in host, use a check constraint:
alter table mytable
add constraint chk_host_upper
check (host rlike '^[A-Z]*$')
;
This prevents lower case character to be written to the column; an attempt to do so results in a runtime error.
If, on the other hand, you want to create a new column, that returns the upper case value of host, regardless of the actual column code:
alter table mytable
add column host_upper varchar(50) -- same as the original column
as (upper(host))
;
With this set up at hand, you can query the new column host_upper when you want the upper case values.
Finally: if you want to convert input value to upper case on the fly on inserts, then you need a trigger:
delimiter //
create trigger mytrigger
before insert on mytable
for each row
begin
set new.host = upper(new.host);
end
//
delimiter ;

You can just assign the host column to have a case insensitive collation:
ALTER TABLE mydb.myTable MODIFY host VARCHAR(255)
CHARACTER SET latin1
COLLATE latin1_swedish_ci;
Now the case of the host you use when inserting does not matter, and you may compare against this column using any case. If you still need to view the host as uppercase, then just use UPPER():
SELECT UPPER(host) AS host_upper
FROM myTable;

Related

mysql add unique multi column with no check actual data

For an mysql v8.0.18 project with mariaDb 10.4.10
I would like add to my existing table an unique constraint for multi columns
ALTER TABLE 'new_purchasseorder' ADD UNIQUE ('created', 'fk_customer_id', 'fk_removal_id', 'fk_recipient_id')
but would like no check for old datas
something like that:
where id > 3869
i also tried the SET FOREIGN_KEY_CHECKS=0; but nor working in this case.
is it possible ?
My table looks like:
You can't do this with a unique constraint as far as I know, because, as you have already discovered, such a constraint will be applied to the entire table, regardless of id value. One workaround might be to use a before insert trigger, which does the assertion:
DELIMITER //
CREATE TRIGGER contacts_before_insert
BEFORE INSERT ON new_purchasseorder FOR EACH ROW
BEGIN
IF EXISTS (SELECT 1 FROM new_purchasseorder
WHERE created = NEW.created AND
fk_customer_id = NEW.fk_customer_id AND
fk_removal_id = NEW.fk_removal_id AND
fk_recipient_id = NEW.fk_recipient_id)
THEN
signal sqlstate '45000';
END IF;
END; //
DELIMITER ;
This insert trigger would cause any insert incoming with what your unique index defines as duplicate data to fail with an error, effectively blocking that insert.
A better long term (and easier) strategy might be to just fix your old data so that it can pass the requirements of the unique constraint.
Starting version 8.0.13, MySQL supports functional key parts - basically indexes on expression. Assuming that all 4 columns are non-nullable, you can do:
create unique index idx_new_purchaseorder on new_purchaseorder (
(
case when id > 3869
then concat_ws('$$', created, fk_customer_id, fk_removal_id, fk_recipient_id)
end
)
)
The case expression filters on id values, and generates a concatenated string that should be unique for rows that comply to the filter. I used some fancy characters to avoid "fake" duplicates.
Demo on DB Fiddle

set default value to field if empty string is inserted through query

So I have table A which contains a column Z with default value set to string "diverse".
The queries come in from a php script which takes the data from a jqueryAJAX post request.
I would like to have my DB set the respective field of column Z to default value if the query received an empty string for insertion into/update of this column.
I really would like to accomplish this using mysql functionality, without using any more custom coded php logic.
I already read about using WHEN/THEN logic here:
Set default value if empty string is passed MySQL
and here
MySQL update CASE WHEN/THEN/ELSE
but these don't explain how I permanently configure a table/column in a way that it exposes this "default" behavior not just on receiving a NULL value, but also on receiving an empty string.
Besides:
If I set a column to NOT NULL and also add a default value for the column, would the query just fail if I tried to insert a/update to a NULL value, or would the DB instead flip to the default value?
MySQL/MariaDB will put the value to a column you specify in the insert/update-statement. If you do not provide a value, the default (if specified) will be used.
If you want to use the default value even if the insert/update-statement does provide a value (NULL / empty string), you will have to have the logic somewhere. The options are that you put the logic in your application code (PHP) or if you want to do it in MySQL/MariaDB, you can use a trigger to check the new value and act accordingly.
CREATE TRIGGER ins_A BEFORE INSERT ON A
FOR EACH ROW
BEGIN
IF NEW.Z is null or NEW.Z='' THEN
SET NEW.Z = 'diverse';
END IF;
END;
And do the same for UPDATE
Please follow 2 case bellow:
create table Test
(
a varchar(400) not null default 'test',
b varchar(10)
)
collate = utf8mb4_unicode_ci;
Case 1:
INSERT INTO Test (a, b) VALUES (NULL, 'case1');
=> resul: error because column a required not null;
Case 2:
INSERT INTO Test (b) VALUES ('case1');
=> OK, and result of column a = defaul value = test

mysql error 1062 during alter table modify column

I have a table that looks like this:
CREATE TABLE t1 (
id BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY,
col1 VARCHAR(256),
UNIQUE INDEX t1_col1_index (col1)
)
I'm trying to modify the col1 type using the following query:
ALTER TABLE t1 MODIFY COLUMN col1 varchar(191) COLLATE utf8mb4_unicode_ci;
However, I run into this duplication error:
error: ("1062", "QMYSQL3: Unable to execute statement", "Duplicate entry '+123456789' for key 't1_col1_index'")
I initially thought it could be because two or more rows might 'contain' similar value for col1 and on changing varchar length the data gets truncated but then I found out that data truncation wouldn't even allow the query to go through. Any pointers on what could be causing this?
EDIT (Resolved): Truncation does happen when ##sql_mode is not set with STRICT_TRANS_TABLES. This was causing the error.
You are reducing the length of a varchar column that is controlled by a UNIQUE constraint.
This is risky business. Oversize data will be silently trimed (unless you have the ##sql_mode set to STRICT_TRANS_TABLES in which case an error will be raised). This probably generates duplicates, which cause the error to be raised by your UNIQUE constraint.
You can check the max length of the values in your column with :
SELECT MAX(CHAR_LENGTH(col1)) FROM t1:
I am not sure if this is work.
Try to check the table t1.
select count(1) from t1 where col1 = 123456789
Now if count is greater than one then try to remove the other one and leave only one record.
Then try to run your statement again.
Reminder:
Do back up first before removing.

Set default value to all columns in a database

I am working in a PHP + MySQL application. The application is working fine for me. But when I hosted it in another server, I got a MySQL error:
Error Code: 1364. Field 'field' doesn't have a default value
I know this is a problem with the MySQL version and we should setup default values for all columns. But currently I have more than 100 tables. So I need to set default value to NULL for all columns in all tables that has no default value yet.
I can't make use of the strict mode option, because the server is a shared one. Is it possible to setup in a single step rather than setting for each and every table ? If not possible tell me the easiest way to setup it.
Any help would be greatly appreciated
For anyone else with this problem, it will take a bit of coding to perform automatically, but the following would be how you would do so:
First run the following query:
SELECT table_schema,table_name,column_name,data_type FROM information_schema.columns WHERE IS_NULLABLE='NO' AND column_default is null AND column_key=''
Next, for each row returned from the above query perform the following:
If data_type contains 'int' set default to 0
else if data_type='datetime' set default to '0000-00-00 00:00:00'
else if data_type='date' set default to '0000-00-00'
else if data_type='time' set default to '00:00:00'
else set default to ''
create and run the following query with all [[...]] variables replaced with their proper values:
ALTER TABLE `[[table_schema]]`.`[[table_name]]` ALTER COLUMN `[[column_name]]` SET DEFAULT '[[default]]'
This should replace the default values for all databases, all tables, all columns that are set to be NOT NULL and are not primary keys and have no default value set.
Another solution that i found is like:-
Get all column name put it in array...
Now push values in column array for inserting -- with ZERO value for all those arrays we do not have values.
FOR EXAMPLE:
in a table we have COLUMN
NAME LASTNAME COMPNAME PHONO EMAIL ADDRESS ALTERPERSON ALTERPHONE ALTEREMAIL
Now after migration we see the eeror
Error Code: 1364. Field 'field' doesn't have a default value
if we run a INSERT QUERY LIKE
mysqli_query($con,'insert into table
(NAME,LASTNAME,COMPNAME,PHONO,EMAIL,ADDRESS) values
(NAME,LASTNAME,COMPNAME,PHONO,EMAIL,ADDRESS)')
now it will give error...
So just turn the table
get all the column value from DB.TABLE
put it in an array or do it like one by one using while loop or for loop....
check insert values for each column
put condition if insert value is equal to ZERO or NULL then insert ZERO it will solve all issues.
WHY ZERO --
because it will work for VARCHAR,TEXT,INT,BIGINT and in many Data Types except time or date function and DATE/TIME data type got ZERO values by default...
=============================== Another option...
run a PHP code
get all TABLE NAME
then for each TABLE NAME
get all COLUMN NAME
and run this command as in function under loop
ALTER TABLE DB.TABLEnAME CHANGE columnNAME_A columnNAME_A
VARCHAR(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL
DEFAULT NULL;
=======================
And its DONE

unexpected error 1054 in sql

After table setup, I suddenly remember to update it by adding one column and assign all the same value to that column. So I wrote the queries on Workbench like this
ALTER TABLE sthebc3_cle ADD COLUMN Species char(30) AFTER Genome_ACC;
SET SQL_SAFE_UPDATES=0;
UPDATE cle.sthebc3_cle
SET Species='StHe';
But it reported error like
error 1054: unknown column "Species" in "field list
I checked table after ALTER, The new column "Species" was indeed added to the column and values are NULL.
How could be the error reported?
You need to make sure that the current session is the database you want. There is always a selected database in MySQL.
If you want to be 100% sure which database you are using you Always put nameofthedatabase.tablename,
For the table
ALTER TABLE cle.sthebc3_cle ADD COLUMN Species char(30) AFTER Genome_ACC;
SET SQL_SAFE_UPDATES=0;
UPDATE cle.sthebc3_cle
SET Species='StHe';
For you view, try this
USE cle;
CREATE VIEW all_cle AS
(SELECT Species, Genome_ACC, CLE_start, CLE_end, CLE_domain
FROM nameofdatabase.cowpea_cle)
UNION
(SELECT Species, Genome_ACC, CLE_start, CLE_end, CLE_domain
FROM nameofdatabase.sthebc3_cle);