DEFAULT 절에 CURRENT_TIMESTAMP가있는 TIMESTAMP 열이 하나만있는 이유는 무엇입니까?


180

DEFAULT 또는 ON UPDATE 절에 CURRENT_TIMESTAMP가있는 TIMESTAMP 컬럼이 하나만있는 이유는 무엇입니까?

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 컬럼은 하나만있을 수 있습니다.


6
실제로 오류 메시지가 표시하는 것보다 훨씬 나쁩니다. 추가 절이 있더라도 데이터 형식 의 열이 있으면 CURRENT_TIMESTAMPin DEFAULT또는 ON UPDATE절로 열을 정의 할 수 없습니다 TIMESTAMP!
Nicolas Buduroi

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)
Nicolas Buduroi

@NicolasBuduroi 첫 번째 timestamp열이 널 입력 가능 여부가 아닙니다 null. 첫 번째 경우 timestamp열은 not null기본적으로 다음 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP추가됩니다. stackoverflow.com/a/13544181/2859238
user104309

@NicolasBuduroi 첫 번째 timestamp열에 명시적인 기본값이 설정되어있는 경우에도 마찬가지 default '0000-00-00 00:00:00'입니다. 열은, 널 (NULL) 또는 명시 적으로 기본 값이 설정되어있는 경우 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP추가되지 않습니다
user104309

그 이유에 대한 답을 정말로보고 싶습니까? 문제를 해결하는 방법이나 문제가 해결되지 않았습니다. 왜 이런 식으로 구현 되었습니까? 그것은 총체적인 방식으로 보이며이 제한의 이유가 될 수있는 디자인 / 구현을 찾을 수 없습니다. 멍청한 사람들이 어떻게 프로그램을 배우고 싶어서 가르쳐주세요.
Lothar

답변:


173

과거의 코드 레거시 이유로 인해이 제한이 최신 버전의 MySQL에서 해제되었습니다.

MySQL 5.6.5의 변경 사항 (2012-04-10, 마일스톤 8)

이전에는 테이블 당 최대 하나의 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 답변도 확인하십시오. 실제로 첫 번째 타임 스탬프 열에는 "업데이트 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
우리가 즐길 수있는 또 하나의 위대한 MySQL 제한!
Nicolas Buduroi

1
@gorn 더 쉬운 솔루션 / 해결 방법은 아래 Scarlett의 것입니다.
tihe

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() 
);

"삽입"동안 두 열 모두에 널을 입력해야합니다.

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. 열의 데이터 유형을 datetime으로 변경
  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

1

업데이트 된 필드에 필드를 넣고 AddedDate가 null 인 경우에만 AddedDate 필드를 UpdatedDate 값으로 업데이트하는 트리거가있을 수 있습니다.


1

다양한 답변을 결합 :

MySQL은 5.5 년, DEFAULT CURRENT_TIMESTAMP그리고 ON UPDATE CURRENT_TIMESTAMP에 추가 할 수 없습니다 DATETIME만에 TIMESTAMP.

규칙 :

1) TIMESTAMP테이블 당 최대 하나의 열을 자동으로 (또는 수동으로 [ My addition ]) 초기화하거나 현재 날짜 및 시간으로 업데이트 할 수 있습니다. (MySQL 문서).

따라서 오직 하나만 in 또는 절을 TIMESTAMP가질 수 있습니다CURRENT_TIMESTAMPDEFAULTON UPDATE

2) 제 1 NOT NULL TIMESTAMP명시없이 열 DEFAULT같은 값을 created_date timestamp default '0000-00-00 00:00:00'암시 적으로 설명한다 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 따라서 후속 TIMESTAMP열이 주어지지 않을 수 CURRENT_TIMESTAMPDEFAULT또는 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

@ ComputerEngineer88 이것은 오래된 mysql 서버에 적합한 솔루션입니다. created_at열을 직접 설정해야합니다 . 나는 이것이 op가 의도적으로 말하고 싶은 것이라고 생각합니다.
Roger

이것은 정확히 공식적인 해결책입니다. dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Rangi Lin

0

이것은 MYSQL 5.5 버전의 제한 사항입니다. 버전을 5.6으로 업데이트해야합니다.

Error

MYSQL에서 테이블을 추가 할 때이 오류가 발생했습니다.

잘못된 테이블 정의; DEFAULT 또는 ON UPDATE 절에 CURRENT_TIMESTAMP가있는 TIMESTAMP 열은 하나만있을 수 있습니다. 새 MYSQL

테이블은 이런 식입니다.

table_name 테이블 작성 (col1 int (5) auto_increment 기본 키, col2 varchar (300), col3 varchar (500), col4 int (3), col5 tinyint (2), col6 타임 스탬프 기본 current_timestamp, col7 타임 스탬프 기본 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.