web-dev-qa-db-ja.com

インデックス作成: '[列]'の無効なデフォルト値

私は10年前のWebアプリ(!!!)に取り組んでおり、現在ローカルでバージョン5.7のmysqlを実行しています。

これは私が現在取り組んでいるテーブルです:

CREATE TABLE `processes_history` (
  `p_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
  `exec_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
  `feature` varchar(100) NOT NULL DEFAULT '',
  `macro` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
  `ts` date NOT NULL DEFAULT '0000-00-00',
  `seen` int(10) UNSIGNED NOT NULL DEFAULT '1',
  `seen_time` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
  `focus` int(10) UNSIGNED NOT NULL DEFAULT '0',
  `focus_time` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
  `mouse` int(10) UNSIGNED NOT NULL DEFAULT '0',
  `keyboard` int(10) UNSIGNED NOT NULL DEFAULT '0',
  `interactive` int(10) UNSIGNED NOT NULL DEFAULT '0',
  `interactive_time` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
  `last_seen` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY RANGE (TO_DAYS(`ts`))
(
PARTITION p0 VALUES LESS THAN (736695) ENGINE=MyISAM,
PARTITION p201701 VALUES LESS THAN (736726) ENGINE=MyISAM,
PARTITION p201702 VALUES LESS THAN (736754) ENGINE=MyISAM,
PARTITION p201703 VALUES LESS THAN (736785) ENGINE=MyISAM,
PARTITION p201704 VALUES LESS THAN (736815) ENGINE=MyISAM,
PARTITION p201705 VALUES LESS THAN (736846) ENGINE=MyISAM,
PARTITION p201706 VALUES LESS THAN (736876) ENGINE=MyISAM,
PARTITION p201707 VALUES LESS THAN (736907) ENGINE=MyISAM,
PARTITION p201708 VALUES LESS THAN (736938) ENGINE=MyISAM,
PARTITION p201709 VALUES LESS THAN (736968) ENGINE=MyISAM,
PARTITION p201710 VALUES LESS THAN (736999) ENGINE=MyISAM,
PARTITION p201711 VALUES LESS THAN (737029) ENGINE=MyISAM,
PARTITION p201712 VALUES LESS THAN (737060) ENGINE=MyISAM,
PARTITION p201801 VALUES LESS THAN (737091) ENGINE=MyISAM,
PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE=MyISAM
);

--
-- Indexes for dumped tables
--

--
-- Indexes for table `processes_history`
--
ALTER TABLE `processes_history`
  ADD PRIMARY KEY (`p_id`,`exec_id`,`feature`,`ts`),
  ADD KEY `ts` (`ts`),
  ADD KEY `exec_ts` (`exec_id`,`ts`),
  ADD KEY `last_seen` (`last_seen`);

p_id, exec_id, tsにインデックスを追加するとエラーが発生し続けます:

ALTER TABLE `dbname`.`processes_history` ADD INDEX `p_id,exec_id,ts` (`p_id`, `exec_id`, `ts`);

エラーSQLクエリ:

ALTER TABLE dbname.processes_history ADD INDEX p_id,exec_id,tsp_idexec_idts)MySQLによると:ドキュメント

1067-'ts'の無効なデフォルト値

この投稿に続く: インデックスの作成時、無効なデフォルト値

私が理解したところによると、0000-00-00をデフォルト値として使用すると、「日付」タイプが壊れます。そのため、機能しません。

しかし、私はこの状況の解決策が何であるか理解できませんでした。代わりにTIMESTAMPタイプを使用していますか?

構造を壊さずにこの問題を解決する方法はありますか?(少なくとも今のところ)ユニット全体を終了しますか?多くのことはそのテーブルに依存しているので、自分が望む方法でインデックスを付けるために危険なことをしたくはありません。

2
Rick Sanchez

@jerichoriveraが問題のポイントになっています。彼の意味を詳しく説明します。

MySQL 5.6からMySQL 5.7に、MySQLはデフォルトの SQL_Mode を「緩い」ものから、より厳密で標準に準拠した「MySQL厳密なモード」に変更しました。その上では、「0000-00-00」のような日付は許可されません。最初に許可されるデータは「1000-01-01」です。他の例はここで見ることができます: https://www.slideshare.net/jynus/query-optimization-with-mysql-57-and-mariadb-10-even-newer-tricks/45

アプリケーションが壊れないようにすぐに修正したい場合は、SQLモードをNO_ENGINE_SUBSTITUTIONに設定してリセットできます。何も壊れず、5.6の動作が得られます。

ただし、スキーマを最終的に「修正」する必要がある場合があります。無効な日付に'0000-00-00'を使用するのは、無効な文字列に空の文字列('')を使用するのと同じくらい悪いです。 Cでは、SQLには無効/不明な状態を表す値があり、それはNULL-無効な日付を表すために使用することをお勧めします(プロパティNULLを使用して暗黙的に行うことができます)。ただし、アプリケーションが列のこの新しい「状態」を考慮し、アプリケーションレベルとデータベースレベルの両方での順序と比較に関するその他の設計想定を考慮する必要があります(たとえば、比較によって常にtrueまたはfalseが返される場合) 、および3番目の状態ではありませんNULL)。

NULLの使用が不可能または望ましくない場合は、許可された範囲内の特別な値を使用できます。これはベストプラクティスではありませんが、少なくとも無効な入力と混合されていません。

カラムが使用されなくなった場合は、ドロップできますか?

すべてのデータベースの問題を修正すると、TRADITIONAL/Strictモードにより、データの一貫性の問題が軽減されます。

4
jynus