10

In MySQL I have a table with Column1 as NOT NULL:

create table myTable 
(
    Column1 int not null,
    Column2 int not null
)

I can still insert an empty value like this:

INSERT INTO `myTable` ( `Column1` ,  `Column2` )
VALUES ( '66', '' );

How can I make the MySQL column also disallow blankstring?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
zac1987
  • 2,721
  • 9
  • 45
  • 61
  • 1
    @zac1987: Can you really insert an empty string into an `int` column? How did you do that (and why did you try?) – ypercubeᵀᴹ Aug 31 '11 at 23:47
  • @Martin Smith, how to check what RDBMS am I using? phpMyadmin is RDBMS? I am using phpMyadmin. – zac1987 Aug 31 '11 at 23:56
  • @ypercube, yes, I can insert an empty string into an int column, but it auto convert it to "0". I want to prevent user insert empty value to database, for example, the user open 2 tabs, he logout his account on 1 tab, then he submit form for 2nd tab, form submission will save empty user_id to database column since he already logout from his account. I think it is better to set database column not to accept empty entry. – zac1987 Aug 31 '11 at 23:57
  • @zac1987 I *think* the back ticks must mean MySQL but hopefully someone else will be able to confirm or give you a way of finding out. – Martin Smith Aug 31 '11 at 23:57
  • @zac1987: You better make your forms not to accept empty strings as values for integer fields. – ypercubeᵀᴹ Sep 01 '11 at 00:01
  • 1
    The only other way I see to enforce such a constraint in MysQL (I suppose you use that), is to add a FOREIGN KEY constraint from `Column2` that referemces `anotherTable(column)` which column has a list of allowed values for `Column2`. – ypercubeᵀᴹ Sep 01 '11 at 00:14
  • 1
    Nice idea (in the absence of real CHECK constrainsts) but don't do this for fields such as monetary values ;) – MatBailie Sep 01 '11 at 00:16
  • Actually it is tbl_friendship which has a composite primary key (owner_id) and (fren_id). They both are foreign keys of tbl_user :) Why must not use for monetary field? Because the value of entries might not be unique? – zac1987 Sep 01 '11 at 00:25
  • Using a *foreign* key you can restrict values in a field to be from a specific list of valid options. UserIDs, country codes, or any property that has a constrained list of possible values fit this perfectly well. Monetry (and other) values, however, can have a near infinite number of legitimate values. Creating the list of legitimate values for "cost" would use up an immense amount of database space. – MatBailie Sep 01 '11 at 10:06
  • @Dems, do you mean those column has long integer value must not be foreign key? my foreign key is an auto increment user_id from tbl_user which will grow until very big integer like 1000000 in future. So the entry value of my column should be the same as Monetry value, so actually I should not set this column as foreign key? – zac1987 Sep 01 '11 at 11:39
  • @zac1987; No. If you have a *dimension* table with a `user_id` as a PRIMARY KEY, then have a *fact* table with `user_id` in it, you **should** make a Foreign Key Constraint. What is being talked about here is using a Foreign Key Constraint as a PRETEND Constraint. Imagine you have an AGE field in your *fact* table. You *could* create an AGE *dimension* table with ages 0 to 120, a foreign key constraint would ensure the Age field could only ever be from 0 to 120. If you wanted to limit a PRICE field from $0.01 to $999,999.99, this trick would be a bad idea as it would need 100million rows. – MatBailie Sep 01 '11 at 11:52
  • @Dems, I think I understood u already. user_id are entered by end-users, so it is considered as **Real Foreign Key**. But price and age are entered by developer, so they are considered as **Pretended Foreign Key**. But user_id of **RFK** is the same as price of **PFK**, both of them have million of rows, the different between them is user_id didn't has so many rows at beginning but Price default already has so many rows at beginning. And all rows of Price must be entered by only 1 person - developer which is lot of works for him... That's why u said **PFK** is bad idea for Monetry field? – zac1987 Sep 01 '11 at 14:26

5 Answers5

10

EMPTY STRINGS

In ORACLE an empty string is used to represent NULL. In virtually everything else, however, an empty string is still a string, and so not NULL.


INTS

In your case you're actually inserting STRINGS into an INT column. This forces an implicit CAST operation.

When your RDBMS is converting the string '' to an INT it must get the value 0. As 0 is not NULL, this gets inserted.

A more valid test would be:

INSERT INTO `plekz`.`countries` (`Column1 ` , `Column2`)
VALUES (66, NULL);


EDIT

Sorry, I only half read your question. You also ask how to stop '' being inserted.

Your first problem is that you're inserting STRINGS and the table is defined as having INT fields. You can put constraints on the data that gets inserted, but these constraints will apply the the value after an conversion to an INT. Unless you want to prevent the value 0 from also being inserted, there is nothing you can do to the table to prevent this scenario.

Your better bet is to address why you are inserting strings in the first place. You could use a stored procedure that takes, and checks, the strings before converting them to INTs and then inserting them. Or, better still, you could make the checks in your client application.

A technically available option is to make the fields CHAR fields, then put a constraint on the fields, preventing '' from being inserted. I would strongly recommend against this.

MatBailie
  • 83,401
  • 18
  • 103
  • 137
  • 1
    If the OP is on MySQL aren't [check constraints just ignored](http://stackoverflow.com/questions/706231/mysql-and-check-constraints)? – Martin Smith Aug 31 '11 at 23:59
  • I see, thank you. I tested Null and saw the error message "#1048 - Column 'Column2' cannot be null". Do I need write php if ($user_id == "") then $user_id = Null; before inserting value of $user_id to database? – zac1987 Sep 01 '11 at 00:02
  • 1
    martin smith: Which, fortunately, is another reason to push the OP towards validating the data before calling his SQL statements. zac1987: That is an option, yes. You are always best sanity checking your data before throwing it at the database. – MatBailie Sep 01 '11 at 00:03
9

You're inserting an empty string, not NULL. The constraint is only against NULL values, and it would appear that your database is not coercing empty strings to NULL when it converts them to INT (which raises the additional question of why you're inserting string literals into INT columns...)

Dan J
  • 16,319
  • 7
  • 50
  • 82
  • Good point. I seem to remember that gets coerced to 0 in MySQL. – Martin Smith Aug 31 '11 at 23:47
  • The corollary here is that you need a `CHECK` constraint to reject empty strings (and possibly strings consisting of only whitespace). – Jeffrey Hantin Sep 01 '11 at 00:03
  • Jeffrey Hantin: The field is an INT, you can't check for an empty string there (the values are converted to INTs before being inserted and so also before the CHECK constraint). Not to mention that MySQL apparently ignores CHECK constraints (I'm not sure why it has them then...) – MatBailie Sep 01 '11 at 00:07
  • @Dems: It has them so CREATE TABLE statements from other RDBMS (with CHECK constraints) not produce errors (I guess). – ypercubeᵀᴹ Sep 01 '11 at 00:11
5

MySQL, how to disallow empty string:

  1. Create your table:

    mysql> create table yar (val VARCHAR(25) not null);
    Query OK, 0 rows affected (0.02 sec)
    
  2. Create your 'before insert' trigger to check for blankstring and disallow.

    mysql> create trigger foo before insert on yar
        -> for each row
        -> begin
        -> if new.val = '' then
        -> signal sqlstate '45000';
        -> end if;
        -> end;$$
    Query OK, 0 rows affected (0.01 sec)
    
  3. Try to insert null and blankstring into your column:

    mysql> delimiter ;
    
    mysql> insert into yar values("");
    ERROR 1644 (45000): Unhandled user-defined exception condition
    
    mysql> insert into yar values(NULL);
    ERROR 1048 (23000): Column 'val' cannot be null
    
    mysql> insert into yar values ("abc");
    Query OK, 1 row affected (0.01 sec)
    
    mysql> select * from yar;
    +-----+
    | val |
    +-----+
    | abc |
    +-----+
    1 row in set (0.00 sec)
    

Finally, Grumble to self and smack the nearest person who was responsible for picking mysql over postgresql.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
3

As Martin mentions, depends on your RDBMS. Oracle treats empty strings as NULLs while others do not. See this SO post.

Community
  • 1
  • 1
JW8
  • 1,496
  • 5
  • 21
  • 36
1

NULL is not equal to emptiness. In MySQL, there is an additional byte with each column entry to hold the "is null" information. To save space, a column is often defined as "not null" to spare this extra byte if the null status doesn't add any thing to the data model.

TVNshack
  • 107
  • 6