Mengapa hanya ada satu kolom TIMESTAMP dengan CURRENT_TIMESTAMP dalam klausa DEFAULT?

180

Mengapa hanya ada satu kolom TIMESTAMP dengan CURRENT_TIMESTAMP dalam DEFAULT atau klausa ONDATE?

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;

Kesalahan yang dihasilkan:

Kode Kesalahan: 1293

Definisi tabel salah; hanya ada satu kolom TIMESTAMP dengan CURRENT_TIMESTAMP dalam DEFAULT atau klausa ON UPDATE

ripper234
sumber
6
Ini sebenarnya jauh lebih buruk daripada apa yang tampak pada pesan kesalahan itu. Anda tidak dapat menentukan kolom dengan CURRENT_TIMESTAMPdi DEFAULTatau ON UPDATEklausa sekali ada kolom dengan TIMESTAMPtipe data, tidak peduli apakah itu mendapat klausul tambahan!
Nicolas Buduroi
9
Jadi ini bekerja CREATE TABLE foo (created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_on TIMESTAMP)CREATE TABLE foo (updated_on TIMESTAMP, created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
:,
@NicolasBuduroi Tidak jika timestampkolom pertama yaitu nullable null. Jika timestampkolom pertama not nullmaka secara default DEFAULT CURRENT_TIMESTAMPdan ON UPDATE CURRENT_TIMESTAMPakan ditambahkan. stackoverflow.com/a/13544181/2859238
user104309
@NicolasBuduroi Juga tidak jika timestampkolom pertama memiliki nilai default yang ditetapkan seperti suka default '0000-00-00 00:00:00'. Jika kolom nullable atau nilai default eksplisit diatur, maka DEFAULT CURRENT_TIMESTAMPdan ON UPDATE CURRENT_TIMESTAMPTIDAK akan ditambahkan
user104309
Akan sangat senang melihat jawaban tentang mengapa? bukan bagaimana menyiasatinya atau bagaimana memperbaikinya sekarang. Mengapa ini pernah diterapkan dengan cara ini? Sepertinya cara braindead total dan saya tidak dapat menemukan desain / implementasi yang mungkin menjadi alasan untuk pembatasan ini. Saya ingin belajar bagaimana program orang bodoh, jadi tolong ajari saya.
Lothar

Jawaban:

173

Keterbatasan ini, yang hanya karena alasan historis dan alasan kode, telah diangkat dalam versi terbaru MySQL:

Perubahan pada MySQL 5.6.5 (2012-04-10, Milestone 8)

Sebelumnya, paling banyak satu kolom TIMESTAMP per tabel dapat secara otomatis diinisialisasi atau diperbarui ke tanggal dan waktu saat ini. Pembatasan ini telah dicabut. Definisi kolom TIMESTAMP apa pun dapat memiliki kombinasi DEFAULT CURRENT_TIMESTAMP dan ON UPDATE CURRENT_TIMESTAMP klausa. Selain itu, klausa ini sekarang dapat digunakan dengan definisi kolom DATETIME. Untuk informasi lebih lanjut, lihat Inisialisasi Otomatis dan Pembaruan untuk TIMESTAMP dan DATETIME.

http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-5.html

augustin
sumber
Periksa juga jawaban @mooli di bawah ini. Sebenarnya kolom timestamp pertama memiliki "default current_timestamp pada pembaruan current_timestamp" secara otomatis diatur (sehingga harus dinamai updated_at). Anda hanya perlu mengatur Created_at secara manual pada waktu memasukkan.
Gismo Ranas
apa yang bisa kita lakukan jika dump mysql milik versi 5.7 dan setup perlu dijalankan pada 5,4
otc
1
@otc, Anda dapat mengedit dump, atau mulai lagi dengan 5.4
Jasen
40

Saya juga sudah lama bertanya-tanya. Saya mencari sedikit dalam sejarah saya dan saya pikir posting ini: http://lists.mysql.com/internals/34919 mewakili posisi semi-resmi MySQL (sebelum intervensi Oracle;))

Pendeknya:

pembatasan ini hanya berasal dari cara di mana fitur ini saat ini diterapkan di server dan tidak ada alasan lain untuk keberadaannya.

Jadi penjelasan mereka adalah "karena diimplementasikan seperti ini". Kedengarannya tidak terlalu ilmiah. Saya kira itu semua berasal dari beberapa kode lama. Ini disarankan di utas di atas: "carry-over mulai dari ketika hanya timestamp pertama yang disetel / diperbarui secara otomatis".

Bersulang!

Lachezar Balev
sumber
Wow, itu benar-benar bau. Semoga kita melihat perbaikan segera.
BoltClock
46
Keterbatasan MySQL lain yang luar biasa untuk kita nikmati!
Nicolas Buduroi
1
@ selamat solusi yang lebih mudah / bekerja di sekitar adalah satu dari Scarlett di bawah ini.
tihe
38

Kami dapat memberikan nilai default untuk cap waktu untuk menghindari masalah ini.

Posting ini memberikan solusi terperinci: 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() 
);

Perhatikan bahwa perlu memasukkan nol ke dalam kedua kolom selama "insert":

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) 
Scarlett
sumber
16

Memang kesalahan implementasi.

Pendekatan asli di MySQL adalah memperbarui tanggal pembuatan sendiri (jika Anda membutuhkannya) dan membuat MySQL khawatir tentang timestamp update date ? update date : creation date seperti:

CREATE TABLE tracked_data( 
  `data` TEXT,
  `timestamp`   TIMESTAMP,
  `creation_date` TIMESTAMP                                   
) ENGINE=INNODB; 

Saat membuat, Masukkan NULL:

INSERT INTO tracked_data(`data`,`creation_date`) VALUES ('creation..',NULL);

Nilai NULL untuk cap waktu diinterpretasikan sebagai CURRENT_TIMESTAMP secara default.

Di MySQL, kolom TIMESTAMP pertama dari sebuah tabel mendapatkan keduanya DEFAULT CURRENT_TIMESTAMPdan ON UPDATE CURRENT_TIMESTAMPatribut, jika tidak ada atribut yang diberikan untuk itu. inilah mengapa kolom TIMESTAMP dengan atribut harus didahulukan atau Anda mendapatkan kesalahan yang dijelaskan dalam utas ini.

mooli
sumber
14
  1. Ubah tipe data kolom ke datetime
  2. Atur pemicu

Seperti:

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 ;
Feng-Chun Ting
sumber
Saya selalu menganggap metode ini jauh kurang menyenangkan dibandingkan fungsionalitas CURRENT_TIMESTAMP yang diimplementasikan setengah.
TehShrike
1

Nah perbaikan untuk Anda bisa dengan meletakkannya di bidang UpdatedDate dan memiliki pemicu yang memperbarui bidang AddedDate dengan nilai UpdatedDate hanya jika AddedDate adalah nol.

HLGEM
sumber
1

Menggabungkan berbagai jawaban:

Di MySQL 5.5, DEFAULT CURRENT_TIMESTAMPdan ON UPDATE CURRENT_TIMESTAMPtidak bisa ditambahkan DATETIMEtetapi hanya aktif TIMESTAMP.

Aturan:

1) paling banyak satu TIMESTAMPkolom per tabel dapat secara otomatis (atau secara manual [ Penambahan saya ]) diinisialisasi atau diperbarui ke tanggal dan waktu saat ini. (MySQL Documents).

Sehingga hanya satu TIMESTAMPdapat memiliki CURRENT_TIMESTAMPdi DEFAULTatau ON UPDATEklausa

2) NOT NULL TIMESTAMPKolom pertama tanpa DEFAULTnilai eksplisit suka created_date timestamp default '0000-00-00 00:00:00'akan secara implisit diberikan DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPdan karenanya TIMESTAMPkolom berikutnya tidak dapat diberikan CURRENT_TIMESTAMPpada DEFAULTatau ON UPDATEklausa

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)

Pilihan lain (Tapi updated_dateadalah kolom pertama):

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;
pengguna104309
sumber
0

Coba ini:

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;
Shoaib Qureshi
sumber
3
Ini akan berhasil tetapi itu tidak menyelesaikan masalah. Created_at adalah 0 yang agak tidak berguna.
CompEng88
@ ComputerEngineer88 Ini adalah solusi tepat untuk server mysql lama. Anda harus mengatur created_atkolom sendiri. Saya pikir inilah yang ingin dikatakan secara sengaja oleh op.
Roger
ini persis solusi resmi, didokumentasikan di sini dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Rangi Lin
0

Ini adalah batasan dalam versi MYSQL 5.5. Anda perlu memperbarui versi ke 5.6.

Error

Saya mendapatkan kesalahan ini dalam menambahkan tabel di MYSQL

Definisi tabel salah; hanya ada satu kolom TIMESTAMP dengan CURRENT_TIMESTAMP dalam DEFAULT atau ON UPDATE klausa MYSQL baru saya

Tabel terlihat seperti ini.

buat 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 pada pembaruan current_timestamp, col8 tinyint (1) default 0, col9 tinyint (1) default 1);

Setelah beberapa waktu membaca tentang perubahan di berbagai versi MYSQL dan beberapa googling. Saya menemukan bahwa ada beberapa perubahan yang dibuat di MYSQL versi 5.6 dari versi 5.5.

Artikel ini akan membantu Anda menyelesaikan masalah. http://www.oyewiki.com/MYSQL/Incorrect-table-definition-there-can-be-only-one-timestamp-column

Ankur Rastogi
sumber