MySQL Error 1265 Data Truncated for Enum - mysql

I have a stored procedure in MySQL that has an enum called log_level with a few values.
..
DECLARE log_level ENUM('none','some','errors','debug') DEFAULT 1;
SET log_level = 0;
..
Gives the error:
If I change this to:
..
DECLARE log_level ENUM('none','some','errors','debug') DEFAULT log_level=1;
SET log_level = 0;
..
It gives the error:
How can I fix this issue?

Same kind issue was occurring with me when i was doing `
ALTERorINSERT
` the information.
I got fixed by
UPDATE TABLE t SET t.fieldName = NULL
and this fixed my issue.

MySQL enums work differently than the C/C++ equivalent. log_level is declared as an enum of strings so it really expects a string as value. A default of '1' doesn't make much sense, either.
The correct syntax is:
DECLARE log_level ENUM('none','some','errors','debug') DEFAULT 'some';
SET log_level = 'none';
The same error 1265 shows up if you try to assign a non-existing value to an enum (e.g. an empty string in stead of a real NULL value).
Sidenote: internally the database uses integer values but those details are completely hidden by the SQL language.

Related

Int value stored as empty string in database, trying to set new value to old value creates a "cannot convert string to int" problem

I have a form which allows users to not input a value for customer_no which is an int value. It is stored in the database as an empty string I presume?
Here is the column customer_no INT(11) NULL,
Why is it stored like this? I am trying to create a trigger for when the value is null or '' to use the old value stored. Yet it has the error of cannot convert string to int. Any help? Here is the trigger body
IF NEW.customer_no IS NULL OR NEW.customer_no= ''
THEN SET NEW.customer_no= OLD.customer_no;
END IF;
[Field error in object 'form' on field 'customer_no ': rejected value []; codes
[typeMismatch.form.customer_no ,typeMismatch.customer_no ,typeMismatch.int,typeMismatch]; arguments
[org.springframework.context.support.DefaultMessageSourceResolvable: codes
[form.customer_no ,customer_no ]; arguments []; default message [customer_no ]]; default message [Failed to
convert property value of type 'java.lang.String' to required type 'int' for
property 'customer_no '; nested exception is java.lang.NumberFormatException: For input
string: ""]]
`
I am using springboot and a jdbc query to get the information from from the form and update the database however when the value is null (rather than an integer value) It shows this error. I want the user to have the option to not enter a value for this field, if they want to update other fields, and still keep the old value previously entered for this particular one.
For example if the previously entered customer_no was 5 in the database and a user updates another column in the database and not enter a value for this field the trigger should use the old value stored of 5 instead of null yet it says "cannot convert string to int"
Hope that made a bit of sense
Thank you
Change the field in the class receiving the form from int to Integer. It should then get a null value, which I think is what you're after.

JSON text is not properly formatted. Unexpected character 'N' is found at position 0

I am new to JSON in SQL. I am getting the error "JSON text is not properly formatted. Unexpected character 'N' is found at position 0." while executing the below -
DECLARE #json1 NVARCHAR(4000)
set #json1 = N'{"name":[{"FirstName":"John","LastName":"Doe"}], "age":31, "city":"New York"}'
DECLARE #v NVARCHAR(4000)
set #v = CONCAT('N''',(SELECT value FROM OPENJSON(#json1, '$.name')),'''')
--select #v as 'v'
SELECT JSON_VALUE(#v,'$.FirstName')
the " select #v as 'v' " gives me
N'{"FirstName":"John","LastName":"Doe"}'
But, using it in the last select statement gives me error.
DECLARE #v1 NVARCHAR(4000)
set #v1 = N'{"FirstName":"John","LastName":"Doe"}'
SELECT JSON_VALUE(#v1,'$.FirstName') as 'FirstName'
also works fine.
If you're using SQL Server 2016 or later there is build-in function ISJSON which validates that the string in the column is valid json.
Therefore you can do things like this:
SELECT
Name,
JSON_VALUE(jsonCol, '$.info.address.PostCode') AS PostCode
FROM People
WHERE ISJSON(jsonCol) > 0
You are adding the Ncharacter in your CONCAT statement.
Try changing the line:
set #v = CONCAT('N''',(SELECT value FROM OPENJSON(#json1, '$.name')),'''')
to:
set #v = CONCAT('''',(SELECT value FROM OPENJSON(#json1, '$.name')),'''')
JSON_VALUE function may first be executed on all rows before applying the where clauses. it will depend on execution plan so small things like having top clause or ordering may have a impact on that.
It means that if your json data is invalid anywhere in that column(in the whole table), it will throw an error when the query is executed.
So find and fix those invalid json formats first. for example if that column has a ' instead of " it cannot be parsed and will cause the whole TSQL query to throw an error

Ambiguous literal error when converting SQL Case on SELECT to SQLAlchemy format

I'm having problems translating the following CASE Statement on SELECT to SQLAlchemy ORM. I keep getting the error : "Ambiguous literal: False. Use the 'text()' function to indicate a SQL expression literal, or 'literal()' to indicate a bound value."
The Case statement checks a variable, and then either returns a column on the database or selects a literal. The literal is set prior to running the sql statement.
DECLARE #str_cntry_cd varchar(3)
SELECT COUNTRY_CD,
CASE WHEN #str_cntry_cd IS NOT NULL THEN RESOLUTION_ID
ELSE 10
END AS RESOLUTION_ID
FROM COUNTRY
The SQLAlchemy code looks as follows:
country_tbl = getattr(main_db.Base.classes, "COUNTRY")
c_res = case([(country_code != None, country_tbl.RESOLUTION_ID),],
else_ = literal(10)).label("resolution_id")
programs_sa = main_db.session.query(country_tbl.COUNTRY_CD.label("country_cd"),
c_res).all()
The table is as follows:
CREATE TABLE dbo.COUNTRY
(
COUNTRY_CD varchar(4) NOT NULL,
RESOLUTION_ID int NOT NULL
)
SQLAlchemy .9.9
Windows 7
SQL Server 2008 R2
Python 2.7
country_code != None is causing the problem.
That evaluates to python's True/False, which SQLAlchemy doesn't know how to convert to SQL's true/false as it is ambiguous. So you would need to either add the literal true/false for the SQL you are using, by using SQLAlchemy's text or literal functions. But a better way would be to use the true or false functions.
http://docs.sqlalchemy.org/en/latest/core/sqlelement.html#sqlalchemy.sql.expression.true
http://docs.sqlalchemy.org/en/latest/core/sqlelement.html#sqlalchemy.sql.expression.false
So you would replace the buggy section of the code with:
db.false() if country is None else db.true()
Hope this helps.

Updating integer column from jsonb member fails with: column is of type integer but expression is of type jsonb

In a PostgreSQL 9.5 table I have an integer column social.
When I try to update it in a stored procedure given the following JSON data (an array with 2 objects, each having a "social" key) in the in_users variable of type jsonb:
'[{"sid":"12345284239407942","auth":"ddddc1808197a1161bc22dc307accccc",**"social":3**,"given":"Alexander1","family":"Farber","photo":"https:\/\/graph.facebook.com\/1015428423940942\/picture?type=large","place":"Bochum,
Germany","female":0,"stamp":1450102770},
{"sid":"54321284239407942","auth":"ddddc1808197a1161bc22dc307abbbbb",**"social":4**,"given":"Alxander2","family":"Farber","photo":null,"place":"Bochum,
Germany","female":0,"stamp":1450102800}]'::jsonb
Then the following code is failing:
FOR t IN SELECT * FROM JSONB_ARRAY_ELEMENTS(in_users)
LOOP
UPDATE words_social SET
social = t->'social',
WHERE sid = t->>'sid';
END LOOP;
with the error message:
ERROR: column "social" is of type integer but expression is of type jsonb
LINE 3: social = t->'social',
^
HINT: You will need to rewrite or cast the expression.
I have tried changing that line to:
social = t->'social'::int,
but then I get the error:
ERROR: invalid input syntax for integer: "social"
LINE 3: social = t->'social'::int,
^
Why doesn't PostgreSQL recognize that the data is integer?
From the JSON-TYPE-MAPPING-TABLE I was having the impression that JSON number would be auto-converted to PostgreSQL numeric type.
A single set-based SQL command is far more efficient than looping:
UPDATE words_social w
SET social = (iu->>'social')::int
FROM JSONB_ARRAY_ELEMENTS(in_users) iu -- in_user = function variable
WHERE w.sid = iu->>'sid'; -- type of sid?
To answer your original question:
Why doesn't PostgreSQL recognize that the data is integer?
Because you were trying to convert the jsonb value to integer. In your solution you already found that you need the ->> operator instead of -> to extract text, which can be cast to integer.
Your second attempt added a second error:
t->'social'::int
In addition to the above: operator precedence. The cast operator :: binds stronger than the json operator ->. Like you found yourself already, you really want:
(t->>'social')::int
Very similar case on dba.SE:
Querying JSONB in PostgreSQL
I've ended up using:
FOR t IN SELECT * FROM JSONB_ARRAY_ELEMENTS(in_users)
LOOP
UPDATE words_social SET
social = (t->>'social')::int
WHERE sid = t->>'sid';
IF NOT FOUND THEN
INSERT INTO words_social (social)
VALUES ((t->>'social')::int);
END IF;
END LOOP;

Mysql recursive procedure

I have a table name css_diectory with 3 columns directory_id, directory-name and root_directory. I am storing hierarchical directory structure in this table. I have written a procedure to retrieve all the descendants given the directory_id. But it doesn't work. Can anyone please help me.
Here is the procedure
CREATE PROCEDURE getDescendants
(IN rootId varchar(32), INOUT desecendantsFolderId varchar(3200))
BEGIN
DECLARE endOfRecord INTEGER DEFAULT 0;
DECLARE folderId varchar(32) DEFAULT "";
DECLARE folderName varchar(32) DEFAULT "";
DECLARE folderCursor CURSOR FOR
Select directory_id, directory_name from css_directory where root_directory=rootId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET endOfRecord = 1;
OPEN folderCursor;
getFolderId: LOOP
FETCH folderCursor INTO folderId, folderName;
IF endOfRecord = 1 THEN
LEAVE getFolderId;
END IF;
Call getDescendants(folderId,desecendantsFolderId);
SET desecendantsFolderId = CONCAT(folderId,",",desecendantsFolderId);
call getDescendants(folderId,desecendantsFolderId);
END LOOP getFolderId;
END
Edit: The output of this procedure is always a null set. It does not produce any error
I'm not 100% sure I follow what you're doing, but it looks like there's a problem here:
SET desecendantsFolderId = CONCAT(folderId,",",desecendantsFolderId);
When any argument to CONCAT() is null, then the return value is null. Presumably descendantsFolderId is initially null, and if so, I don't see where that would change.
There are several ways to remedy this, but here is one of them:
SET desecendantsFolderId = NULLIF(CONCAT_WS(",",folderId,desecendantsFolderId),"");
CONCAT_WS() is like CONCAT(), except the first argument is used as a separator amd null arguments beyond the first one are disregarded, and empty string is returned if all subsequent arguments are null. NULLIF() is probably not technically needed, based on the rest of the code, but will ensure that the final result of CONCAT_WS() will be turned back to null if the input args are indeed all null.