MySQL 4.0にCreatedとLast Updatedの両方のタイムスタンプ列がある


127

次のテーブルスキーマがあります。

CREATE TABLE `db1`.`sms_queue` (
  `Id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `Message` VARCHAR(160) NOT NULL DEFAULT 'Unknown Message Error',
  `CurrentState` VARCHAR(10) NOT NULL DEFAULT 'None',
  `Phone` VARCHAR(14) DEFAULT NULL,
  `Created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `LastUpdated` TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP,
  `TriesLeft` tinyint NOT NULL DEFAULT 3,
  PRIMARY KEY (`Id`)
)
ENGINE = InnoDB;

次のエラーで失敗します。

ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause.

私の質問は、私はそれらの両方のフィールドを持つことができますか?または、各トランザクション中にLastUpdatedフィールドを手動で設定する必要がありますか?


@Xenph Yanさん、「承認済み」の回答を現在の間違ったものから正しいものに変更してもよろしいですか?この受け入れられた間違った答えは、何が起こっているのかを理解しようとして約15分を失いました...
Bruno Reis

1
@BrunoReis完了、受け取りありがとう。
Xenph Yan

回答:


128

以下からのMySQL 5.5のドキュメント

テーブルの1つのTIMESTAMP列には、列を初期化するためのデフォルト値、自動更新値、またはその両方として現在のタイムスタンプを含めることができます。現在のタイムスタンプを1つの列のデフォルト値にして、別の列の自動更新値にすることはできません。

MySQL 5.6.5の変更

以前は、テーブルごとに最大で1つのTIMESTAMP列を自動的に初期化したり、現在の日時に更新したりできました。この制限は解除されました。TIMESTAMP列の定義には、DEFAULT CURRENT_TIMESTAMP句とON UPDATE CURRENT_TIMESTAMP句の任意の組み合わせを含めることができます。さらに、これらの句をDATETIME列定義で使用できるようになりました。詳しくは、TIMESTAMPおよびDATETIMEの自動初期化および更新を参照してください。


これは変更されました(少なくともMySQL 5.0では)。ドキュメントを参照してください:dev.mysql.com/doc/refman/5.0/en/timestamp.html
SimonSimCity

@SimonSimCityに対抗する:5.0のドキュメントは、上記とまったく同じことを言っています。
davemyron

5
@RobertGambleより興味深い質問は、なぜ彼らがこの非常に一般的に要求されている/必要な機能を実行する方法を提供していないのかと思います。
Ray

22
これはMySQLの側では少し恣意的です。これが事実である理由を誰かが説明できますか?
humble_coder 2012

12
本当に本当に古いコメント、しかし、それが最終的に変更されました: Changes in MySQL 5.6.5 (2012-04-10, Milestone 8) Previously, at most one TIMESTAMP column per table could be automatically initialized or updated to the current date and time. This restriction has been lifted. Any TIMESTAMP column definition can have any combination of DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses. In addition, these clauses now can be used with DATETIME column definitions. For more information, see Automatic Initialization and Updating for TIMESTAMP and DATETIME.
マウリシオ・バルガス

83

両方のタイムスタンプを持つトリックがありますが、少し制限があります。

1つのテーブルで使用できる定義は1つだけです。次のように両方のタイムスタンプ列を作成します。

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中に両方の列に入力する必要があることに注意してくださいinsert

mysql> insert into test_table(stamp_created, stamp_updated) values(null, null); 
Query OK, 1 row affected (0.06 sec)

mysql> select * from test_table; 
+----+---------------------+---------------------+ 
| 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-Documentationからのリンクは次のとおり
refman

6
最初のコードボックスは、手動で入力すると完全に機能しました。ありがとう!この答えがベーコンを救ったので、この答えを支持するのに十分な「カルマ」があればいいのに mmmmm保存ベーコン。
amatusko

これstamp_created もNOT NULLに設定されていることを確認する必要があります。MySQLは自動的にNULLを現在のタイムスタンプに置き換えます。
Valentin Despa 2014年

「ZERO」値を使用する代わりに、stamp_createdフィールドを次のstamp_created timestamp default now()ようにしてみませんか?
セバスチャンショール

28

両方を作成することができます。作成されたフィールドの「CURRENT_TIMESTAMP」フラグを外すだけです。テーブルに新しいレコードを作成するときは常に、値に "NOW()"を使用してください。

または。

逆に、「ON UPDATE CURRENT_TIMESTAMP」フラグを削除し、そのフィールドにNOW()を送信します。その方法は実際にはもっと理にかなっています。


2
これが唯一の方法ですか?データベースを細部にわたって管理することはできませんか?
Xenph Yan

2
MySqlマニュアルによると、CURRENT_TIMESTAMPはNOW()の同義語であるため、これは機能しないと思います。
tvanfosson 2008年

きっとできます。CURRENT_TIMESTAMPは、1つのフィールドでのみ予約されているフラグです。どちらの方法でも、そこにそのフラグがあった場合、レコードを追加するときにそのフィールドにどのような値があるかに関係なく、それは常に現在のタイムスタンプ、つまり名前になります。
スティーブンウォルチャー

1
@tvanfosson:クエリで 'NOW()'を使用すると、現在の時刻がデータベースに渡されます。その値が実際に何であるかは、言語、エンジン、およびおそらく私が知らない他の百のものに依存します。私が参照していたフラグは、レコードが作成されると、そのフィールドに時刻が追加されるように設定します。
スティーブンウォルチャー

2
他のコードがこれらのテーブルに触れる可能性があり、人々がそれらを正しく更新することを信頼していないため、私は挿入NOW()方法を採用しました。:)
Xenph Yan

26

MySQLでタイムスタンプの更新を処理する場合は、挿入時にフィールドを更新するトリガーを設定できます。

CREATE TRIGGER <trigger_name> BEFORE INSERT ON <table_name> FOR EACH ROW SET NEW.<timestamp_field> = CURRENT_TIMESTAMP;

MySQLリファレンス:http : //dev.mysql.com/doc/refman/5.0/en/triggers.html


これは私が探していたものです。クエリにNOW()を追加したユーザーに依存する必要はありません。
ボット

実際には、挿入後に行い、NEW。<timestamp_field> = new。<timestamp_field>を設定すると、両方のフィールドが
一致し

@KacieHouserトリガー後の新しい行の更新は許可されていません
Thomas

23

これは、トリガーを使用して自動で柔軟なcreateDate / lastModifiedフィールドを持つ方法です。

まず、次のように定義します。

CREATE TABLE `entity` (
  `entityid` int(11) NOT NULL AUTO_INCREMENT,
  `createDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `lastModified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `name` varchar(255) DEFAULT NULL,
  `comment` text,
  PRIMARY KEY (`entityid`),
)

次に、これらのトリガーを追加します。

DELIMITER ;;
CREATE trigger entityinsert BEFORE INSERT ON entity FOR EACH ROW BEGIN SET NEW.createDate=IF(ISNULL(NEW.createDate) OR NEW.createDate='0000-00-00 00:00:00', CURRENT_TIMESTAMP, IF(NEW.createDate<CURRENT_TIMESTAMP, NEW.createDate, CURRENT_TIMESTAMP));SET NEW.lastModified=NEW.createDate; END;;
DELIMITER ;
CREATE trigger entityupdate BEFORE UPDATE ON entity FOR EACH ROW SET NEW.lastModified=IF(NEW.lastModified<OLD.lastModified, OLD.lastModified, CURRENT_TIMESTAMP);
  • あなたがいる場合に挿入 CREATEDATEまたはLASTMODIFIEDを指定せずに、彼らは現在のタイムスタンプに等しいとセットになります。
  • createDateまたはlastModifiedを指定せずにそれらを更新すると、lastModifiedは現在のタイムスタンプに設定されます。

しかし、これは良い部分です:

  • 挿入する場合、現在のタイムスタンプよりも古いcreateDateを指定できます。これにより、古い時刻からのインポートが適切に機能します(lastModifiedはcreateDateと等しくなります)。
  • 更新する場合は、以前の値よりも古いlastModified( '0000-00-00 00:00:00'は適切に機能します)を指定して、表面的な変更(コメントのタイプミスの修正)を行っている場合にエントリを更新できます。 )そして、古いlastModifiedの日付を保持したい場合。これにより、lastModifiedの日付は変更されません。

21

MySQL 5.6の時点で、簡単で簡単に試してみてください。

create table tweet ( 
    id integer not null auto_increment primary key, 
    stamp_created timestamp default now(), 
    stamp_updated timestamp default now() on update now(),
    message varchar(163)
)

おそらく素晴らしい解決策私が探しているものは、トリガーなしで作成と更新の
時間の問題

この小さな迷惑が解消されるのにこれほど長い時間がかかったなんて信じられません。彼らがこれを修正したことに気づかなかったし、それは2018年だ...ありがとう。
hsanders 2018年

4

この問題はMySQL 5.6で解決されたようです。MySQL 5.5までこれに気づきました。ここにサンプルコードがあります:

DROP TABLE IF EXISTS `provider_org_group` ;
CREATE TABLE IF NOT EXISTS `provider_org_group` (
  `id` INT NOT NULL,
  `name` VARCHAR(100) NOT NULL,
  `type` VARCHAR(100) NULL,
  `inserted` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `insert_src_ver_id` INT NULL,
  `updated` TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP,
  `update_src_ver_id` INT NULL,
  `version` INT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC),
  UNIQUE INDEX `name_UNIQUE` (`name` ASC))
ENGINE = InnoDB;

これをMySQL 5.5で実行すると、次のようになります。

ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

これをMySQL 5.6で実行する

0 row(s) affected   0.093 sec


2

mysql 5.7.21の場合、以下を使用して正常に動作します。

CREATE TABLE Postsmodified_atタイムスタンプNOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP、 created_atタイムスタンプNOT NULL DEFAULT CURRENT_TIMESTAMP)


1

これはstamp_createdとstamp_updatedのより良いクエリだと思います

CREATE TABLE test_table( 
    id integer not null auto_increment primary key, 
    stamp_created TIMESTAMP DEFAULT now(), 
    stamp_updated TIMESTAMP DEFAULT '0000-00-00 00:00:00' ON UPDATE now() 
); 

レコードが作成されたときので、stamp_createdによって満たされるべきnow()stamp_updatedによって満たされる必要があります'0000-00-00 00:00:00'


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