DEFAULT句またはON UPDATE句にCURRENT_TIMESTAMPを持つTIMESTAMP列が1つしか存在できないのはなぜですか?
CREATE TABLE `foo` (
`ProductID` INT(10) UNSIGNED NOT NULL,
`AddedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`UpdatedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=INNODB;
結果として生じるエラー:
エラーコード:1293
誤ったテーブル定義。 DEFAULT句またはON UPDATE句にCURRENT_TIMESTAMPを持つTIMESTAMP列は1つのみ存在できます。
この制限は、歴史的なコードレガシーの理由のみによるものでしたが、MySQLの最近のバージョンで解除されました。
MySQL 5.6.5の変更(2012-04-10、マイルストーン8)
以前は、テーブルごとに最大で1つのTIMESTAMP列を自動的に初期化または現在の日時に更新することができました。この制限は解除されました。 TIMESTAMP列定義には、DEFAULT CURRENT_TIMESTAMP句とON UPDATE CURRENT_TIMESTAMP句の任意の組み合わせを含めることができます。さらに、これらの句をDATETIME列定義で使用できるようになりました。詳細については、TIMESTAMPおよびDATETIMEの自動初期化と更新を参照してください。
http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-5.html
私もその昔、疑問に思いました。私は自分の歴史を少し検索しましたが、この投稿: http://lists.mysql.com/internals/34919 は半公式を表していますMySQLの位置(Oracleの介入前;))
要するに:
この制限は、この機能が現在サーバーに実装されている方法にのみ起因し、他に存在する理由はありません。
彼らの説明は「このように実装されているから」です。あまり科学的ではないようです。それはすべて古いコードから来ていると思います。これは上記のスレッドで提案されています:「最初のタイムスタンプフィールドのみが自動設定/更新されたときからの繰り越し」。
乾杯!
この問題を回避するために、タイムスタンプにデフォルト値を指定できます。
この投稿は詳細な回避策を提供します: http://gusiev.com/2009/04/update-and-create-timestamps-with-mysql/
create table test_table( id integer not null auto_increment primary key, stamp_created timestamp default '0000-00-00 00:00:00', stamp_updated timestamp default now() on update now() );
「挿入」中に両方の列にヌルを入力する必要があることに注意してください。
mysql> insert into test_table(stamp_created, stamp_updated) values(null, null); Query OK, 1 row affected (0.06 sec) mysql> select * from t5; +----+---------------------+---------------------+ | id | stamp_created | stamp_updated | +----+---------------------+---------------------+ | 2 | 2009-04-30 09:44:35 | 2009-04-30 09:44:35 | +----+---------------------+---------------------+ 2 rows in set (0.00 sec) mysql> update test_table set id = 3 where id = 2; Query OK, 1 row affected (0.05 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from test_table; +----+---------------------+---------------------+ | id | stamp_created | stamp_updated | +----+---------------------+---------------------+ | 3 | 2009-04-30 09:44:35 | 2009-04-30 09:46:59 | +----+---------------------+---------------------+ 2 rows in set (0.00 sec)
確かに実装の失敗。
MySQLのネイティブアプローチでは、作成日を自分で更新し(必要な場合)、MySQLにtimestampupdate date ? update date : creation date
を心配させます:
CREATE TABLE tracked_data(
`data` TEXT,
`timestamp` TIMESTAMP,
`creation_date` TIMESTAMP
) ENGINE=INNODB;
作成時にNULLを挿入:
INSERT INTO tracked_data(`data`,`creation_date`) VALUES ('creation..',NULL);
タイムスタンプのNULL値は、デフォルトでCURRENT_TIMESTAMPとして解釈されます。
MySQLでは、属性が指定されていない場合、テーブルの最初のTIMESTAMPカラムはDEFAULT CURRENT_TIMESTAMP
とON UPDATE CURRENT_TIMESTAMP
の両方の属性を取得します。これが、属性を持つTIMESTAMP列が最初に来なければならない理由です。そうしないと、このスレッドで説明されているエラーが発生します。
といった:
DROP TRIGGER IF EXISTS `update_tablename_trigger`;
DELIMITER //
CREATE TRIGGER `update_tablename_trigger` BEFORE UPDATE ON `tablename`
FOR EACH ROW SET NEW.`column_name` = NOW()
//
DELIMITER ;
さまざまな回答の組み合わせ:
MySQL 5.5では、DEFAULT CURRENT_TIMESTAMP
とON UPDATE CURRENT_TIMESTAMP
はDATETIME
に追加できませんが、TIMESTAMP
にのみ追加できます。
ルール:
1)テーブルごとに最大1つのTIMESTAMP
列を自動的に(または手動で(My additional))初期化または現在の日時に更新できます。 (MySQL Docs)。
したがって、TIMESTAMP
またはCURRENT_TIMESTAMP
句にON UPDATE
を含めることができるDEFAULT
は1つだけです。
2)NOT NULL
のような明示的なTIMESTAMP
値を持たない最初のcreated_date timestamp default '0000-00-00 00:00:00'
DEFAULT
列にはDEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
が暗黙的に与えられるため、後続のTIMESTAMP
列はできません。 DEFAULT
またはCURRENT_TIMESTAMP
句でON UPDATE
が与えられます
CREATE TABLE `address` (
`id` int(9) NOT NULL AUTO_INCREMENT,
`village` int(11) DEFAULT NULL,
`created_date` timestamp default '0000-00-00 00:00:00',
-- Since explicit DEFAULT value that is not CURRENT_TIMESTAMP is assigned for a NOT NULL column,
-- implicit DEFAULT CURRENT_TIMESTAMP is avoided.
-- So it allows us to set ON UPDATE CURRENT_TIMESTAMP on 'updated_date' column.
-- How does setting DEFAULT to '0000-00-00 00:00:00' instead of CURRENT_TIMESTAMP help?
-- It is just a temporary value.
-- On INSERT of explicit NULL into the column inserts current timestamp.
-- `created_date` timestamp not null default '0000-00-00 00:00:00', // same as above
-- `created_date` timestamp null default '0000-00-00 00:00:00',
-- inserting 'null' explicitly in INSERT statement inserts null (Ignoring the column inserts the default value)!
-- Remember we need current timestamp on insert of 'null'. So this won't work.
-- `created_date` timestamp null , // always inserts null. Equally useless as above.
-- `created_date` timestamp default 0, // alternative to '0000-00-00 00:00:00'
-- `created_date` timestamp,
-- first 'not null' timestamp column without 'default' value.
-- So implicitly adds DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP.
-- Hence cannot add 'ON UPDATE CURRENT_TIMESTAMP' on 'updated_date' column.
`updated_date` timestamp null on update current_timestamp,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8;
INSERT INTO address (village,created_date) VALUES (100,null);
mysql> select * from address;
+-----+---------+---------------------+--------------+
| id | village | created_date | updated_date |
+-----+---------+---------------------+--------------+
| 132 | 100 | 2017-02-18 04:04:00 | NULL |
+-----+---------+---------------------+--------------+
1 row in set (0.00 sec)
UPDATE address SET village=101 WHERE village=100;
mysql> select * from address;
+-----+---------+---------------------+---------------------+
| id | village | created_date | updated_date |
+-----+---------+---------------------+---------------------+
| 132 | 101 | 2017-02-18 04:04:00 | 2017-02-18 04:06:14 |
+-----+---------+---------------------+---------------------+
1 row in set (0.00 sec)
その他のオプション(ただし、updated_date
は最初の列です):
CREATE TABLE `address` (
`id` int(9) NOT NULL AUTO_INCREMENT,
`village` int(11) DEFAULT NULL,
`updated_date` timestamp null on update current_timestamp,
`created_date` timestamp not null ,
-- implicit default is '0000-00-00 00:00:00' from 2nd timestamp onwards
-- `created_date` timestamp not null default '0000-00-00 00:00:00'
-- `created_date` timestamp
-- `created_date` timestamp default '0000-00-00 00:00:00'
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8;
それは、UpdatedDateフィールドに配置し、AddedDateがnullの場合にのみUpdatedDate値でAddedDateフィールドを更新するトリガーを設定することで解決できます。
これを試して:
CREATE TABLE `test_table` (
`id` INT( 10 ) NOT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE = INNODB;
これはMYSQL 5.5バージョンの制限です。バージョンを5.6に更新する必要があります。
Error
MYSQLにテーブルを追加するときにこのエラーが発生していました
誤ったテーブル定義。 DEFAULTまたはON UPDATE句にCURRENT_TIMESTAMPを持つTIMESTAMP列は1つだけです
テーブルは次のようになります。
create table table_name(col1 int(5)auto_increment primary key、col2 varchar(300)、col3 varchar(500)、col4 int(3)、col5 tinyint(2)、col6 timestamp default current_timestamp、col7 timestamp default current_timestamp on update current_timestamp、 col8 tinyint(1)デフォルト0、col9 tinyint(1)デフォルト1);
さまざまなMYSQLバージョンの変更といくつかのグーグルについて読んだ後。 MYSQLバージョン5.6でバージョン5.5に加えられた変更がいくつかあることがわかりました。
この記事は、問題の解決に役立ちます。 http://www.oyewiki.com/MYSQL/Incorrect-table-definition-there-can-be-only-one-timestamp-column