Why is my MySQL unique key failing? - mysql

INSERT INTO `ree`.`media`
(`CREATEDATE`, `FILETYPE`, `MIMETYPE`, `MLSNUMBER`, `MODIFYDATE`, `POSITION`, `URL`) VALUES
('2011-12-27T15:00:16', 'PRIMARY PHOTO', 'image/jpeg', 5030011414, '2011-12-27T15:00:16', 1, 'http://image.realcomponline.com/photos.rps?PATH=PROPERTY/57FA/57FAA44C48854C/3QQGONGA03I7CN.jpg&g=100&sp=0&l=0&t=0&r=10000&b=10000&o=0&1cf=0&w=320&h=240'),
('2011-12-27T15:00:18', 'PRIMARY PHOTO', 'image/jpeg', 5030011507, '2011-12-27T15:00:18', 1, 'http://image.realcomponline.com/photos.rps?PATH=PROPERTY/6FC7/6FC7B6F88D8F45/3SQGONGA01RXH1.jpg&g=100&sp=0&l=0&t=0&r=10000&b=10000&o=0&1cf=0&w=320&h=240')
Error: Duplicate entry '2147483647-1' for key 'uneek'
It seems like my UNIQUE key of MLSNUMBER isn't parsing the entire number before differentiating the two inserts.
Both start with 5030011...
Here is how I build my the key:
ADD UNIQUE uneek ( MLSNUMBER , POSITION )
Is there a way to build this key so it accepts the entire 10 digits instead of the first 7 digits?
Thanks in advance!

You have run out of range of int.
2147483647 = 2^31 - 1
You might change this int on that field to be e.g. 64bit:
ALTER TABLE media MODIFY COLUMN MLSNUMBER BIGINT NOT NULL;
(Modify unsigned and not null for your needs).

It seems that you've defined the MLSNUMBER column as an Integer type, and the large values are getting truncated to the largest 32 bit signed value, which is 2147483647.
I verified this by attempting to add the value 5030011507 to an Int column, and it ended up storing the value 2147483647. That matches the number in your error message. I also received a warning when the value was truncated.
You can try changing the column type to BIGINT, which will allow values up to 9223372036854775807.

Related

How to insert a json object with ORACLE 19 and 21

Because I don't use Oracle 21. I can't use the JSON type in the definition of a table.
CREATE TABLE TABLE_TEST_QUERY_2
(
TTQ_NR INTEGER GENERATED BY DEFAULT AS IDENTITY,
TTQ_QUERY_TO_BE_TESTED VARCHAR2 (4000 BYTE),
TTQ_RESULT CLOB,
--RESULT JSON, UPGRADE oracle 21
TTQ_TTQ_CREATION_DATE DATE DEFAULT SYSDATE,
TTQ_ALREADY_TESTED INTEGER DEFAULT 0,
TTQ_TEST_PASSED INTEGER,
PRIMARY KEY (TTQ_NR),
CONSTRAINT RESULT CHECK (TTQ_RESULT IS JSON)
)
I want to add a json object in ttq_result. Not a string representing a json.
I've a way to transform a json into a clob.
select to_clob(utl_raw.cast_to_raw (json_object('a' value 2))) from dual;
But it's not working, if I try to insert the clob created from a json in the table
INSERT INTO BV_OWN.TABLE_TEST_QUERY_2 TTQ_RESULT
VALUES to_clob(utl_raw.cast_to_raw (json_object(a value '2')));
[Error] Execution (3: 13): ORA-03001: unimplemented feature
code(oracle 18)
update:
I've tried to add a json on dbfiddle with oracle 21. I'm using the json type to define a column.
CREATE TABLE TABLE_TEST_QUERY_2
(
TTQ_NR INTEGER GENERATED BY DEFAULT AS IDENTITY,
TTQ_QUERY_TO_BE_TESTED VARCHAR2 (4000 BYTE),
TTQ_RESULT JSON,
TTQ_TTQ_CREATION_DATE DATE DEFAULT SYSDATE,
TTQ_ALREADY_TESTED INTEGER DEFAULT 0,
TTQ_TEST_PASSED INTEGER,
PRIMARY KEY (TTQ_NR)
)
INSERT INTO TABLE_TEST_QUERY_2 TTQ_RESULT
VALUES json_object('a' value 2);
I have the same error.
ORA-03001: unimplemented feature
Maybe are these 2 problems related.
code oracle 21
Your first problem is because you are using the wrong syntax as you have omitted the brackets from around column identifiers or the column value:
INSERT INTO BV_OWN.TABLE_TEST_QUERY_2 (TTQ_RESULT)
VALUES ( to_clob(utl_raw.cast_to_raw (json_object(a value '2'))));
Which fixes the unimplemented feature exception but now you get:
ORA-00984: column not allowed here
Which is because you are using a different query to the SELECT as you have changed json_object('a' value 2) to json_object(a value '2') and the query cannot find a column a.
If you fix that by using the original code from the SELECT with 'a' as a string literal and not a a column identifier:
INSERT INTO BV_OWN.TABLE_TEST_QUERY_2 (TTQ_RESULT)
VALUES ( to_clob(utl_raw.cast_to_raw (json_object('a' value 2))));
You will then get the error:
ORA-02290: check constraint (FIDDLE_FCJHJVMCPHKXUCUPDUSV.RESULT) violated
Because converting to a RAW and then to a CLOB will mangle the value.
You need something much simpler:
INSERT INTO BV_OWN.TABLE_TEST_QUERY_2 (TTQ_RESULT)
VALUES (json_object('a' value 2));
or:
INSERT INTO BV_OWN.TABLE_TEST_QUERY_2 (TTQ_RESULT)
VALUES (EMPTY_CLOB() || json_object('a' value 2));
Which both work.
db<>fiddle here

Should I input 2 digit numbers in TINYINT?

I need a column that can store values from -1 (negative 1) to +15 (positive 15).
I am using a TINYINT(2) column at the moment and it works just fine.
I need to know if this is ideal and safe to use because I read online that TINYINT should ONLY be used for binary value such as 1 and 0.
MySQL TINYINT has a storage of 1 byte.
Unsigned value in range 0 to 255 or signed value of range -128 to 127 can be stored.
Also note that 2 in TINYINT(2) does not limit the length of your value to 2 digits. more info in this link - What is the size of column of int(11) in mysql in bytes?
TINYINT will store your value perfectly fine; however it will not guarantee that it will be correct (exactly in that range). Please note that (2) is just related to padding when selecting via the command line and it has nothing to do with the limit. Normally you do not need it at all. TINYINT (signed) will store values from -128 to 127 regardless if you add (n) at the end of it or not.
If you want to make sure that the value is always exactly in the range between -1 and 15, you have two options:
Using CHECK constraint over the existing TINYINT (recommended solution):
CREATE TABLE tiexample(
val TINYINT NOT NULL,
CONSTRAINT val_range CHECK(val>=-1 AND val<=15)
);
INSERT INTO tiexample(val) VALUES(122);
ERROR 4025 (23000): CONSTRAINT `val_range` failed for `test`.`tiexample`
INSERT INTO tiexample(val) VALUES(12);
Query OK, 1 row affected (0.001 sec)
Listing all values as ENUM:
CREATE TABLE tiexample(
val ENUM("-1","0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15") NOT NULL,
CONSTRAINT val_range CHECK(val<>"")
);
INSERT INTO tiexample(val) VALUES("122");
ERROR 4025 (23000): CONSTRAINT `val_range` failed for `test`.`tiexample`
INSERT INTO tiexample(val) VALUES("12");
Query OK, 1 row affected (0.001 sec)
Note that using this method you must insert the values with quotes (like "8", not just 8). Also first it may seem strange that we use CHECK constraint here but it is needed because by default inserting invalid value on ENUM field will insert an empty string in the table (not NULL - it's an empty string). You can get around that issue and skip the CHECK constraint if you use this sql mode before inserting into the table:
SET SQL_MODE = 'Traditional';
Personally I would not struggle with the ENUM type. It is more suitable for different use-cases.
Footnote: CHECK constraints are available and working only in MySQL MySQL 8.0.16+ and MariaDB 10.2.1+. Prior versions accept the constraint but never use it (it will ignore them).

SQL server smallmoney data type error

CREATE TABLE GroovyExps_Tgt
(EMPNO SMALLINT,
FIRSTNAME VARCHAR(20) NOT NULL,
MIDINIT CHAR(1) NOT NULL,
LASTNAME VARCHAR(15) NOT NULL,
SALARY_INT INT,
SALARY_Decimal DECIMAL,
SALARY_Numeric NUMERIC,
SALARY_FLOAT FLOAT(9),
SALARY_MONEY MONEY,
SALARY_SMALLMONEY SMALLMONEY,
BIRTHDATE DATE,
HIREDATE_DATETIME DATETIME,
JOIN_TIME TIME,
JOINTIME DATETIME)
insert into GroovyExps_Tgt values(000080,'LEE','B','BRETT',11111111.11111111,
11111111.11111111,11111111.11111111,
11111111.11111111,11111111.11111111,
11111111.11111111,'1985-05-10',
'2014-04-22 20:25:48.002','20:25','2014-04-22 20:25:48.002')
Error:
Msg 8115, Level 16, State 4, Line 1 Arithmetic overflow error
converting numeric to data type smallmoney. The statement has been
terminated.
I need to insert exact data into table without any change in table definition!!!!
As the error message suggests, this error happens when converting a character or string value, whether of char, varchar, nchar or nvarchar data type, into a smallmoney data type and the character value has invalid characters that cannot be converted to smallmoney data type.
As per your insert statement 11111111.11111111 this value you are
using as a smallmoney value. Smallmoney datatype takes 4 bytes to
store the value in range of -214,748.3648 to +214,748.3647. Now you
see you are using large value for smallmoney that's why it's giving
you error.
The problem is that value 11,111,111 exceeds smallmoney's maximum allowed value which is between - 214,748.3648 and 214,748.3647. For more details you can refer to:
http://msdn.microsoft.com/en-us/library/ms179882.aspx
It is not possible to insert that value in that table without changing its definition, using the money data type yo can accomplish it... could you please tell me what you are trying to accomplish there, so I may help you better?

Adding record in MySQL using forward engineering and there was an error for inserting in Numeric Data Type

First lets see how my table structure is set:
CREATE TABLE IF NOT EXISTS `RFVPOS`.`Station` (
`id` INT NOT NULL AUTO_INCREMENT,
`code` VARCHAR(20) NOT NULL,
`name` VARCHAR(45) NOT NULL,
`safeDropAmount` DECIMAL(4,4) NOT NULL,
`deadStockVolume` DECIMAL(4,4) NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
And here is what MySQL forward engineering does:
`INSERT INTO `rfvpos`.`station` (`code`, `name`, `safeDropAmount`, `deadStockVolume`) VALUES ('test', 'test',` '100', '300');
Im aware that by enclosing my safeDropAmount and deadStockVolume with single qoutes would mean they are in a varchar datatype, so im removing them like this:
`INSERT INTO `rfvpos`.`station` (`code`, `name`, `safeDropAmount`, `deadStockVolume`) VALUES ('test', 'test', 100, 300);
But either ways, when i execute these scripts they say the same thing. this:
ERROR 1264: 1264: Out of range value for column 'safeDropAmount' at row 1
Kindly help me. I was using MySQL before, and after 3 years i'm back again at it, so i'm kinda refreshing.
Best regards,
The column datatype DECIMAL(4,4) won't allow for a value larger than 0.9999 to be stored. Attempting to store value greater than that (for example, 300) would give the "out of range" error.
DECIMAL(4,4) specifies a total of four digits, with four of them (all of them) after the decimal point, leaving zero digits before the decimal point.
If we want to allow values up to 9999.9999, we'd want datatype DECIMAL(8,4).
That's a total of eight digits, with four of those digits after the decimal point, the remainder (8-4) before the decimal point.
Also, MySQL will evaluate the values in single quotes as numeric, in a numeric context, such as inserting into DECIMAL column. The addition or removal of the single quotes around the numeric values, e.g. 300 or '300', has no effect, and they will be evaluated the same. (The difference is what error is returned, if we have a value that isn't numeric (invalid column vs .re is a difference in the error returned what we specify as a literal is not a numeric... foo would raise "Unknown column" error, 'foo' would raise "Incorrect value" error.

Strict matching of strings and integers

I am writing a flexible search mechanism for a customer's website. I am utilizing union clauses to query a number of different fields in the database in search of a string value entered by the user. This works fine except for one issue.
When comparing a string of a text to an integer that is currently set to zero, the match always returns true. In other words, according to MySQL, "email#example.com" is equal to 0.
I have tried utilizing the CAST and CONVERT function to turn this into a standard string to string comparison, but I can't seem to get the syntax right. My attempts either repeat the above issue or return no rows at all when some should match. I am also concerned that doing this would have an effect on performance since I am combining lots of unions.
What I really need is a strict comparison between an entered string and the value in the database, be it an integer or string.
EDIT:
Here is an example.
CREATE TABLE `test_table` (
`id` INT NOT NULL AUTO_INCREMENT ,
`email` VARCHAR(255) NOT NULL ,
`phone` BIGINT(19) NOT NULL DEFAULT '0' ,
PRIMARY KEY (`id`) )
ENGINE = MyISAM;
INSERT INTO `test_table` (`id`, `email`, `phone`) VALUES (1, 'email#example.com', 0);
SELECT * FROM test_table WHERE phone = 'email#example.com';
Execute this and the one row that has been inserted will return. My issue is that it shouldn't!
This query should fail:
SELECT * FROM test_table WHERE cast(phone as char) = 'email#example.com';
The cause of the original problem is that when comparing strings and numbers, it converts the string to a number (so you can write where phone = '123'). You need to use an explicit cast of the field to make it a string-to-string comparison, to prevent this default conversion.
Unfortunately, casting like this is likely to prevent it from using indexes. Even if the field is already char, the cast apparently prevents it from indexing.
You could also solve it during input validation: if phone is an integer, don't allow the user to provide a non-integer value in the search field.
How about replacing:
SELECT * FROM test_table WHERE phone = 'email#example.com'
with:
SELECT * FROM test_table WHERE phone = 'email#example.com' and phone <> 0
<> means different from.
This will work for you because you are using 0 in the phone column to mean there isn't a phone number (although it would be better style to use NULL for no phone number).