Can char field retain trailing space character? - mysql

I have a database table with a primary key called PremiseID.
Its MySQL column definition is CHAR(10).
The data that goes into the column is always 10 digits, which is either a 9-digit number followed by a space, like '113091000 ' or a 9-digit number followed by a letter, like '113091000A'.
I've tried writing one of these values into a table in a test MySQL database table t1. It has three columns
mainid integer
parentid integer
premiseid char(10)
If I insert a row that has the following values: 1,1,'113091000 ' and try to read row back, the '113991000 ' value is truncated, so it reads '113091000'; that is the space is removed. If I insert a number like '113091000A', that value is retained.
How can I get the CHAR(10) field retain the space character?
I have a programmatic way around this problem. It would be to take the len('113091000'), realize it's nine characters, and then realize a length of 9 infers there is a space suffix for that number.

To quote from the MySQL reference:
The length of a CHAR column is fixed to the length that you declare when you create the table. The length can be any value from 0 to 255. When CHAR values are stored, they are right-padded with spaces to the specified length. When CHAR values are retrieved, trailing spaces are removed.
So there's no way around it. If you're using MySQL 5.0.3 or greater, then using VARCHAR is probably the best way to go (the overhead is only 1 extra byte):
VARCHAR values are not padded when they are stored. Handling of trailing spaces is version-dependent. As of MySQL 5.0.3, trailing spaces are retained when values are stored and retrieved, in conformance with standard SQL. Before MySQL 5.0.3, trailing spaces are removed from values when they are stored into a VARCHAR column; this means that the spaces also are absent from retrieved values.
If you're using MySQL < 5.0.3, then I think you just have to check returned lengths, or use a character other than a space.
Probably the most portable solution would be to just use CHAR and check the returned length.

Q: How can I get the CHAR(10) field retain the space character?
Actually, that space is retained and stored. It's the retrieval of the value that's removing the spaces. (The removal of the trailing spaces on returned values is a documented "feature".)
One option (as a workaround) is to modify your SQL query to append trailing spaces to the returned value, e.g.
SELECT RPAD(premiseid,10,' ') AS premiseid FROM t1
That will return your value with as a character string with a length of 10 characters, padded with spaces if the value is shorter than 10 characters, or truncated to 10 characters if its longer.

A standard CHAR(10) column will always have trailing spaces to pad out the string to the required length of 10 characters. As such, any deliberately trailing spaces will be blended in and, typically, stripped by your database adapter.
If possible, convert to a VARCHAR(10) column if you want to preserve the trailing spaces. You can do this with the ALTER TABLE statement.

Though Gordon's answer may still be right by itself, there is on later versions than mentioned a solution.
In your code run SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
With this session setting you'll retrieve perfect columns on full length of the CHAR(10), while VARCHAR does not when no trailing spaces are entered beforehand. If you don't need the spaces, you can always rtrim().

Related

What is the difference between utf8mb4_unicode_ci and utf8mb4_unicode_nopad_ci?

I chose the utf8mb4 character set for my database.
What is the difference between the utf8mb4_unicode_ci and the utf8mb4_unicode_nopad_ci collations?
From the doc
A 'nopad' as part of the name indicates that the collation is of type NO PAD as opposed to PADSPACE ... NO PAD collations regard trailing spaces as normal characters.
On PADSPACE
CHAR (as well as VARCHAR and TEXT) values are compared without regard for trailing spaces. This does not apply to the LIKE pattern-matching operator, which takes into account trailing spaces.
If a unique index consists of a column where trailing pad characters are stripped or ignored, inserts into that column where values differ only by the number of trailing pad characters will result in a duplicate-key error.

How can I store a space character in a MySQL CHAR field?

I have a MySQL Table with a CHAR(1) field. I store single characters in it. Sometimes I need to store a space in this field, but MySQL doesn't let me. I'm using MySQL v.5.6.22.
This runs but an empty field is stored:
INSERT INTO
companies(name_char_0)
values(' ');
This returns an empty value:
SELECT HEX(name_char_0)
FROM companies;
I don't experience this problem with VARCHAR(1) fields, but I have a series of these CHAR fields as lookups and speed is an issue. I believe the VARCHAR(1) field will always be slower to search on than a CHAR(1) field.
In CHAR fields, spaces are used to pad the field to its length, then the spaces are stripped:
From https://dev.mysql.com/doc/refman/5.0/en/char.html:
The length of a CHAR column is fixed to the length that you declare when you create the table. The length can be any value from 0 to 255. When CHAR values are stored, they are right-padded with spaces to the specified length. When CHAR values are retrieved, trailing spaces are removed.
You should not use type CHAR if you want to hold only a space.
If you use VARCHAR(1) in MySQL > 5.0.2 you should not experience this issue:
As of MySQL 5.0.3, trailing spaces are retained when values are stored and retrieved, in conformance with standard SQL. Before MySQL 5.0.3, trailing spaces are removed from values when they are stored into a VARCHAR column; this means that the spaces also are absent from retrieved values.

MYSQL disable Auto-Trim

If I enter two Strings with only white space. I will Get this error message:
ERROR 1062: Duplicate entry ' ' for key 'PRIMARY'
How can I Turn off "Auto-Trim" ?
I'm Using this Charset: uft8-uft8_bin and This Datatype: Varchar.
According to the SQL 92 documentation, when two strings are compared they are first made equal in length by padding the shortest string with spaces.
Search for 8.2 <comparison predicate> in the document.
If the length in characters of X is not equal to the length
in characters of Y, then the shorter string is effectively
replaced, for the purposes of comparison, with a copy of
itself that has been extended to the length of the longer
string by concatenation on the right of one or more pad char-
acters, where the pad character is chosen based on CS. If
CS has the NO PAD attribute, then the pad character is an
implementation-dependent character different from any char-
acter in the character set of X and Y that collates less
than any string under CS. Otherwise, the pad character is a
<space>.
So in other words. Its not about storing the value with the amount of spaces you entered, but its the comparisment it does to check for duplicate primary key. So you cannot have two strings with a different amount of spaces act as a primary key

Quoting of decimal values

I am storing a running total in a Decimal(10,2) field and adding to it as items are processed.
update foo set bar = bar + '3.15'
About 20% of the times a warning is issued "Data truncated for column 'bar' at row 4"
This warning is never issued if the update value is not quoted.
Should decimal values be quoted?
Of course not.
Integers and floats are not strings and should never be quoted. Only MySQL even allows quotes around them.
Is it possible that the value you add exceeds the limits of Decimal(10,2)?
E.g.
update foo set bar = bar + '3.149999'
would cause a 'Data truncated' warning since the field can only store 2 digits to the right of the decimal point (not 6).
No, The decimal values are specified as is. If you quote them it will interpret as a varchar.
No! Quotes are used for strings only, like text, char, varchar, etc

VBA Trim() function truncating text oddly!

I'm trying to trim extraneous white space at the end of a memo field in MS Access. I've tried doing it a number of ways:
1) an update query with the field being updated to Trim([fieldname]). For some reason, that doesn't do anything. The whitespace is still there.
2) an update using a Macro function in which the field contents are passed as a String and then processed using the Trim() function and passed back. This one is really bizarre, in that it seems to truncate the text in the field at completely random places (different for each record). Sometimes 366 characters, sometimes 312, sometimes 280.
3) same as above but with RTrim()
How can I possibly be messing up such a simple function?! Any help much appreciated. Would like to keep my hair.
-Sam
According to this article:
Both Text and Memo data types store only the characters entered in a field; space characters for unused positions in the field aren't stored.
As hypoxide suggested, they may not in fact be spaces
Edit
I suspect that the last character in the field is a carriage return or linefeed character. If this is the case, then Trim (or any variations of Trim - RTrim\LTrim) won't work since they only remove space characters. As 'onedaywhen' suggested in the comment, try using the ASC function to determine the actual character code of the last character in the memo field. You can use something like the following in a query to do this:
ASC(Right(MyFieldName,1))
Compare the result of the query to the Character Set to determine the actual character that ends the memo field. (Space = 32, Linefeed = 10, Carriage Return = 13).
You may have to test the last character and if it is a linefeed or carriage return remove the character and then apply the trim function to the rest of the string.
This may date me, but does Access have different character types for fixed vs. variable lengths? in SQL, CHAR(10) will always by 10 chars long, padded if necessary, while VARCHAR(10) will be 'the' size up to 10. Truncating a CHAR(10) will just put the blanks back.