DEFAULT句にCURRENT_TIMESTAMPを含むTIMESTAMP列が1つしかないのはなぜですか。


180

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つしか存在できません


6
これは実際には、エラーメッセージによって表示される内容よりもはるかに悪いものです。データ型の列があると、追加の句を取得しているかどうかに関係なく、CURRENT_TIMESTAMPin DEFAULTまたはON UPDATE句で列を定義することはできませんTIMESTAMP
Nicolas Buduroi、2011年

9
:この作品そうCREATE TABLE foo (created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_on TIMESTAMP)ではなく、この:CREATE TABLE foo (updated_on TIMESTAMP, created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
ニコラスBuduroi

@NicolasBuduroi最初のtimestamp列がNULL可能である場合、つまりnull。最初のtimestamp列がnot nullデフォルトの場合DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP追加されます。stackoverflow.com/a/13544181/2859238
user104309 2017

@NicolasBuduroiまた、最初のtimestamp列に明示的なデフォルト値が設定されている場合も同様default '0000-00-00 00:00:00'です。列はNULL可能であるか、明示的にデフォルト値が、その後、設定されている場合、DEFAULT CURRENT_TIMESTAMPおよびON UPDATE CURRENT_TIMESTAMP追加されません
user104309

なぜその理由を知りたいですか?どのようにそれを回避するか、どのように修正されたかではありません。なぜこれがこの方法で実装されたのですか?それは完全に頭の痛い方法のようであり、この制限の理由である可能性のある設計/実装を見つけることができません。馬鹿な人のプログラムの仕方を学びたいので教えてください。
Lothar

回答:


173

この制限は、歴史的なコードのレガシーの理由によるものでしたが、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


以下の@mooliの回答も確認してください。実際、最初のタイムスタンプカラムには、「update current_timestampのデフォルトのcurrent_timestamp」が自動的に設定されています(そのため、updated_atという名前にする必要があります)。挿入時にcreated_atを手動で設定する必要があります。
Gismo Ranas

mysqlダンプが5.7バージョンに属していて、セットアップを5.4で実行する必要がある場合はどうすればよいですか
otc

1
@otc、ダンプを編集するか、5.4からやり直すことができます
Jasen

40

私もずっと前にそれを疑問に思いました。私は自分の歴史の中でビットを検索し、私がこの記事だと思います:http://lists.mysql.com/internals/34919は MySQLの半公式の立場を表し(Oracleの介入前に;))

要するに:

この制限は、この機能が現在サーバーに実装されている方法にのみ起因し、その存在には他の理由はありません。

だから彼らの説明は「このように実装されているから」です。あまり科学的に聞こえません。私はそれがすべていくつかの古いコードから来ていると思います。これは上記のスレッドで提案されています:「最初のタイムスタンプフィールドのみが自動設定/更新されたときのキャリーオーバー」。

乾杯!


うわー、それは本当に悪臭を放ちます。すぐに修正されることを願っています。
BoltClock

46
私たちが楽しむためのもう1つの大きなMySQLの制限!
Nicolas Buduroi、2011年

1
@gornより簡単な解決策/回避策は、以下のScarlettのものです。
2013年

38

この問題を回避するために、タイムスタンプのデフォルト値を指定できます。

この投稿は詳細な回避策を提供します: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() 
);

「挿入」時に両方の列にnullを入力する必要があることに注意してください。

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) 

16

確かに実装エラーです。

MySQLのネイティブアプローチは、作成日を自分で更新し(必要な場合)、MySQLに次のようにタイムスタンプを 心配させるupdate 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_TIMESTAMPON UPDATE CURRENT_TIMESTAMP属性の両方を取得します。これが、属性を持つTIMESTAMP列が最初に来る必要があるか、このスレッドで説明されているエラーが発生する理由です。


14
  1. 列のデータ型を日時に変更する
  2. トリガーを設定

といった:

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 ;

私は常に、この方法を、半分実装されたCURRENT_TIMESTAMP機能よりもはるかに扱いにくいと考えてきました。
TehShrike、2011

1

それを修正するには、UpdatedDateフィールドに配置し、AddedDateがnullの場合にのみ、AddedDateフィールドをUpdatedDate値で更新するトリガーを設定することができます。


1

さまざまな答えを組み合わせる:

MySQL 5.5では、DEFAULT CURRENT_TIMESTAMPおよびにのみON UPDATE CURRENT_TIMESTAMP追加できません。DATETIMETIMESTAMP

ルール:

1)TIMESTAMPテーブルごとに最大で1つの列を自動(または手動で[ 追加 ])で初期化または現在の日付と時刻に更新できます。(MySQLドキュメント)。

だから、一つだけをTIMESTAMP持つことができますCURRENT_TIMESTAMPDEFAULTまたはON UPDATE

2)最初のNOT NULL TIMESTAMP明示せずにカラムDEFAULTのような値をcreated_date timestamp default '0000-00-00 00:00:00'暗黙的に説明するDEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPと、従ってそれに続くTIMESTAMP列を与えることができないCURRENT_TIMESTAMP上にDEFAULT、または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;

0

これを試して:

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;

3
これは機能しますが、問題は解決しません。created_atは0です。これは一種の役に立たないものです。
CompEng88 14

@ ComputerEngineer88これは、古いmysqlサーバーに適したソリューションです。created_at自分で列を設定する必要があります。これは、opが意図的に言いたいことだと思います。
Roger、

これはまさに公式のソリューションであり、dev.mysql.com / doc / refman / 5.5 / en / timestamp
Rangi Lin

0

これはMYSQL 5.5バージョンの制限です。バージョンを5.6に更新する必要があります。

Error

MYSQLでテーブルを追加するときにこのエラーが発生しました

不正なテーブル定義。DEFAULT句またはON UPDATE句にCURRENT_TIMESTAMPが指定されたTIMESTAMP列は1つしかありません。新しいMYSQL

テーブルは次のようになります。

create table table_name(col1 int(5)auto_increment primary key、c​​ol2 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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.