MySql SET datatye - mysql

i try to make column in my database table , with set data type to store in it data in this fomat " 10,2,44" i made SET column like this SET('A' , 'B' , 'C')
but when i try to insert data in it i got this response
Error Code: 1265. Data truncated for column 'setcol' at row 1
and this is my query
INSERT INTO `voting`.`questionnaires` (`name`, `cat_id`, `init_date`, `end_date`, `setcol`) VALUES ('sad', '2', '2008-02-02', '2008-02-02', 'A, B');
should i use specific format ? and does set accept repetition ?

To set your desired value you would store a 3 (without quotes) instead of 'A,B'. That is because values in a SET field are stored numerically in bitwise fashion. So each value in a set definition corresponds to on/off bits in a binary number.
Therefore you statement would be:
INSERT INTO `voting`.`questionnaires` (`name`, `cat_id`, `init_date`, `end_date`, `setcol`) VALUES ('sad', '2', '2008-02-02', '2008-02-02', 3);
For example, from the MySQL Documentation:
For a column specified as SET('a','b','c','d'), the members have the
following decimal and binary values.
So since A has a value of 1 and B has a value of 2, add them together and you get 3. Or to set C and D you would store 12, etc.
For this reason, it's ill-advised to have numbers as members of a SET field (as you hinted you might) since storing '5' has a completely different meaning than storing 5.

Related

Subtract number from enum

My number column in data table has enum values:
1, 2, 3, 4, 5, 101, 102, 103, 104, 105
I want to set values of number = number - 100 for all rows using query:
UPDATE data SET data.number = (data.number - 100) WHERE data.number > 100
But it does not work on enum data.
This is a little complicated.
Mysql doesn'z allow number to be cast from ENUM, because the says that numbers should not be used as ENUM value.
but as you need the value if the ENUM field you can convert it into characters.
The final step is to convert that text into a number.
Schema (MySQL v5.7)
CREATE TABLE IF NOT EXISTS `data` (
number ENUM('1', '2', '3', '4', '5', '101', '102', '103', '104', '105')
) ;
INSERT INTO `data` VALUES ( '103');
UPDATE `data` SET number = CAST(CAST(`number` AS CHAR) AS UNSIGNED) - 100 WHERE CAST(CAST(`number` AS CHAR) AS UNSIGNED) >= 100;
Query #1
SELECT * FROM `data`;
| number |
| ------ |
| 3 |
View on DB Fiddle
You can only do arithmetic operations on cardinal numbers (integer, float, double, decimal, date). An enum datatype is nominal.
You could try casting it within SQL but if this operation should be possible the issue is that you have chosen the wrong data type.
That you are exclusively using digits to represent states should have been a red flag.
But it does not work on enum data.
Of course. The string values of ENUM datatype are not the values stored in table data body - it contains 2-byte index of the value only, and according string values list is stored in table definition area which is not available for changing by any DML operation. Only DDL (ALTER TABLE) may change ENUM value string representation definition.
The posted query will treate data.number as index value - so you must get the error (source values are 1-10, final values will be negative whereas ENUM index values are UNSIGNED).

MySql INSERT...ON DUPLICATE UPDATE with partial VALUES

I have a list of possibly-incomplete set of values that will be used to append to or update a MySql table using the INSERT...ON DUPLICATE KEY UPDATE construct. The requirements are as follows:
If an operation resolves to an INSERT and the field value IS supplied, use the value supplied;
If an operation resolves to an INSERT and the field value IS NOT supplied, use the field's table DEFAULT value;
If an operation resolves to an UPDATE and the field value IS supplied, use the value supplied;
If an operation resolves to an UPDATE and the field value IS NOT supplied, retain the current (table) field value.
I've come up with the following statement, but the clauses wrapped in ** are erroneous and I'm having difficulty expressing them:
INSERT INTO `test`
(`id`, `num`, `text`)
VALUES
('1', 100, 'aaa'),
('2', 200, DEFAULT),
('3', DEFAULT, 'ccc')
ON DUPLICATE KEY UPDATE
`num` = IF (**VALUES(`num`) = DEFAULT**, `num`, VALUES(`num`)),
`text` = IF (**VALUES(`text`) = DEFAULT**, `text`, VALUES(`text`));
Notes: id is the unique key. Both num and text have default (NOT NULL) values set.
Things I've tried, but aren't satisfactory:
Replacing DEFAULT in VALUES with NULL, and then test for, e.g., IF (VALUES (num) = NULL .... This works, but will insert NULL on INSERT (and generate a warning - e.g., "Column 'text' cannot be null"), which is not acceptable - I need to have the default value applied to the missing fields;
Using something like 'xxx' instead of DEFAULT for missing values, and testing for 'xxx' (STRCMP), but this will insert 'xxx' in case of INSERT;
I've not tried this as I can't find the command/proper syntax, but the idea is to test (in the IF clause) whether num and text in VALUES are literals (num or string) or a MySql keyword (i.e., DEFAULT) - possibly using regex? - and then act accordingly.
Of course, an alternative to the above might entail obtaining existing values from the database and/or hardcoding into the query the default values for the missing fields, but I trust the same result can be achieved more elegantly using a single MySql statement.
Thanks in advance for your feedback.

SQL Patch that will change all INT values to JSON

I have a table called photoProcess. There is a column within this table photoProcess.storyId.
Currently, all values within the storyId column are being stored as a single integer. I am changing the column type to VARCHAR so that I can store the values as JSON. My question is how I can write a MySQL patch that will change all storyId values of these values to a JSON string.
Example:
Original photoProcess.storyId value for the first row is 6649.
I'd like to change that value to ["6649"] and do so on a large scale for all others.
Use CONCAT:
UPDATE photoProcess SET storyId = CONCAT('["', storyId , '"]')

mysql prepared statement set default value for insert

I've got a table with two columns that links a row id from one table to a row id of another, basically I need to be able to insert multiple rows on this table where one column is a fixed value for the insert and the other changes. The insert is done in php using prepared statements and there is an unknown number of rows to be inserted (I've solved this part using call_user_func_array).
Here is an example of what I need to do:
example_table (column_A, column_B)
The insert:
INSERT INTO example_table (column_A, column_B) VALUES(a, b), VALUES(a, c), VALUES(a, d);
Translated to prepared statement:
INSERT INTO example_table (column_A, column_B) VALUES(?, ?), VALUES(?, ?), VALUES(?, ?);
values on bind_param:
('ssssss', 'a', 'b', 'a', 'c', 'a', 'd')
As you can see the repetition of 'a'. is there a way to store 'a' and default it to column_A for the current insert only?
example of what i would like to do on bind_param:
('ssss', 'a', 'b', 'c', 'd')
Where 'a' above is used for column_A on all rows inserted (3 rows in the example). Any help would be appreciated
No, it's not possible to "alias" a value multiple times. Each placeholder is unique and must be bound to exactly one value. (It is not even possible to do this reliably with named parameters in PDO.)
If automatically building SQL dynamically (with placeholders) and associated data array, then there is no issue with such "duplication" as it's already handled by the generator.
If transactions are correctly used - which they should be anyway! - then simply calling INSERT in a loop, once for each pair, will likely have similar performance. This avoids needing to build the dynamic SQL (with placeholders) itself, but can increase latency as each command needs to round-trip to the SQL server.
If finding a bunch of such repetition, it might be time to use a Data Access Layer to hind such details; write it, test it, move onto something interesting.
In response to the comment about using SQL variables:
While the following will not improve performance, excepting possibly for ridiculously large values of #v, and makes the code more difficult to understand - it ought to be possible to use user-defined variables in a single insert statement. For instance, consider:
INSERT INTO t VALUES (#v := ?, ?), (#v, ?), (#v, ?)
This is "valid" in MySQL (and is also MySQL-specific), where the placeholders are valid expressions; if it works will depend on how/if such a binding is allowed in a prepared statement.
You may try making a temporary table:
$query='CREATE TEMPORARY TABLE tempTable(column_B VARCHAR(50));';
$mysqli->query($query);
then insert unique values of column_B into this table
and finally
$query="INSERT INTO example_table (column_A, column_B) select $a , column_B from tempTable";
$mysqli->query($query);

Storing numbers in a MySQL SET column

How should I insert numbers in a SET column? I know that for ENUM it's recommended to not store numbers in ENUM column, and numbers should be insert with ''.
Is it the same for a SET column? Should be numbers inserted with ''? Like '1','2' or is it fine to insert it like: 1, 2 ?
You insert using SET values names and enclose them in single quotes and separate them with commas.
Minimalistic example from here:
CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));
INSERT INTO myset (col) VALUES ('a,d,d,s');
First of all, don't use MySQL's SET and ENUM column types.
Second, your set definition really shouldn't contain numbers. 'One' is OK, '1' will be extremely confusing.
Third, if you insert numerals like 1, 2, etc then it will actually insert the n-th member of the set instead of that number, whereas if you insert '1' it will insert that member. The difference comes up when you have a set with the following members in that order: 'foo', 'bar', '1', '2' - if you insert '1' it would be the same as inserting a 3, but if you insert a 1 it'd be the same as 'foo'.
Bottom line: don't use the SET and ENUM column types.
Number should insert like 1 ,2 ,3.
This consider as character if you put into single quote like '1','2'.