MySQL empty-string vs SQLite NULL

1bqhqjot  于 2022-10-22  发布在  Mysql
关注(0)|答案(1)|浏览(224)

During work on a legacy codebase I started to write some tests.
Tests run with an underlying sqlite-DB.
I've encountered a problem where an empty model-value could easily be stored by a MariaDB (Prod-ENV) or MySQL (Staging-ENV) while it failed when using the sqlite3 test-database.
As the tables are created from migrtions, the same configuration is used in all three systems:

Schema::create('consumers', function (Blueprint $table) {
  $table->bigIncrements('id');
  $table->integer('type');
  $table->string('name', 512);
  $table->string('xd_number', 512);
  $table->string('guid', 512);
  $table->string('country_iso', 2);
  $table->string('language_iso', 5);
  $table->string('software_version', 128)->nullable();
  $table->integer('online_count')->default(0);
  $table->integer('download_count')->default(0);
  $table->boolean('is_locked')->default(false);
  $table->timestamp('locked_at')->nullable();
  $table->timestamp('last_online_at')->nullable();
  $table->timestamps();
});

The php-code which "produces" the data which is then filled up whith "empty-strings" (maybe, from whatever) is this one:

$consumer = new Consumer();

$consumer->type = $data['type'];
$consumer->xd_number = $login;
$consumer->guid = $this->_createGuid();
$consumer->country_iso = $data['country_iso'];
$consumer->language_iso = $this->_getLanguageIso($request);
$consumer->software_version = $request->input('softwareVersion') ? $request->input('softwareVersion') : null;

$consumer->save();

So, this is a fresh instance of the Model and the name -property is never called.
I also tried to insert a record with PhpMyAdmin, leaving the name column empty although it is set as NOT NULL.
Even that worked as PhpMyAdmin shows the resulting query with all empty string-columns set to '' (empty string):

INSERT INTO `consumers` (`id`, `type`, `name`, `xd_number`, `guid`, `country_iso`, `language_iso`, `software_version`, `online_count`, `download_count`, `is_locked`, `locked_at`, `last_online_at`, `auth_response`, `created_at`, `updated_at`)  
VALUES (NULL, '1', '', '', '', '', '', NULL, '0', '0', '0', NULL, NULL, NULL, NULL, NULL);

A model-property which is not set returns, as a normal php class property, NULL when called.
Am I guessing right, that this means, the NULL -value is turned into '' during the save? Probably by the database?
What do I miss, that MySQL and MariaDB both replace NULL by '' but SQLite tries to insert NULL into this column and complains about the integrity constraint violation?

Integrity constraint violation:  
19 NOT NULL constraint failed: consumers.name
insert into "consumers" ("type", "xd_number", "guid", "country_iso", "language_iso", "software_version", "updated_at", "created_at")  
values (1, FooBar, da55d74c10e1eb31503ec96767268cd0, DE, de-DE, ?, 2022-08-31 00:30:17, 2022-08-31 00:30:17)
eit6fx6z

eit6fx6z1#

from MariaDB documentation :
If a NULL value is single-row inserted into a column declared as NOT NULL, an error will be returned. However, if the SQL mode is not strict (default until MariaDB 10.2.3), if a NULL value is multi-row inserted into a column declared as NOT NULL, the implicit default for the column type will be inserted (and NOT the default value in the table definition). The implicit defaults are an empty string for string types, and the zero value for numeric, date and time types.
This means it is not a Laravel issue, but the database itself. I have the same problem and unfortunately didn't find a solution for SQLite and it doesn't look like there is any.

相关问题