Como você define um valor padrão para uma coluna MySQL Datetime?

898

Como você define um valor padrão para uma coluna MySQL Datetime?

No SQL Server é getdate(). Qual é o equivalente para o MySQL? Estou usando o MySQL 5.x se isso é um fator.

Brian Boatright
fonte
4
Eu uso CURRENT_TIMESTAMP na minha tabela mysql (não na consulta), talvez isso possa ser útil também.
Ruben
15
Este recurso foi adicionado ao MySQL 5.6.5. Espero que isso ajude alguém. optimize-this.blogspot.co.uk/2012/04/…
GhostInTheSecureShell 3/12/12
O @GhostInTheSecureShell tem a missão de instalá-lo, pelo menos no Debian, mas definitivamente um recurso incrível. Acho que eventualmente todas essas "duas perguntas CURRENT_TIMESTAMP" serão atenuadas!
21413 Marc Marcio
agora é a função () ou você pode fazer as configurações padrão no nível da coluna.
Anshul Sharma

Respostas:

862

EDIÇÃO IMPORTANTE: Agora é possível conseguir isso com os campos DATETIME desde o MySQL 5.6.5 , dê uma olhada no outro post abaixo ...

As versões anteriores não podem fazer isso com DATETIME ...

Mas você pode fazer isso com o TIMESTAMP:

mysql> create table test (str varchar(32), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.00 sec)

mysql> desc test;
+-------+-------------+------+-----+-------------------+-------+
| Field | Type        | Null | Key | Default           | Extra |
+-------+-------------+------+-----+-------------------+-------+
| str   | varchar(32) | YES  |     | NULL              |       | 
| ts    | timestamp   | NO   |     | CURRENT_TIMESTAMP |       | 
+-------+-------------+------+-----+-------------------+-------+
2 rows in set (0.00 sec)

mysql> insert into test (str) values ("demo");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+---------------------+
| str  | ts                  |
+------+---------------------+
| demo | 2008-10-03 22:59:52 | 
+------+---------------------+
1 row in set (0.00 sec)

mysql>

** CAVEAT: se você definir uma coluna com CURRENT_TIMESTAMP ON como padrão, precisará SEMPRE especificar um valor para essa coluna ou o valor será redefinido automaticamente para "now ()" na atualização. Isso significa que, se você não deseja que o valor seja alterado, sua instrução UPDATE deve conter "[nome da sua coluna] = [nome da sua coluna]" (ou algum outro valor) ou o valor se tornará "agora ()". Estranho, mas é verdade. Eu espero que isso ajude. Estou usando o 5.5.56-MariaDB **

sebthebert
fonte
400
é importante observar que a data e hora tem um intervalo de 1000 a 9999, mas o intervalo para o registro de data e hora é apenas de 1970 a 2038 . isso pode ser um problema se o seu sistema precisar armazenar datas de nascimento ou se você precisar lidar com algo como o plano de pagamento de uma hipoteca de 30 anos. dev.mysql.com/doc/refman/5.0/en/datetime.html
Kip
13
Tenha cuidado também com timestamp como ele atualizações automáticas magicamente ... ver próxima resposta stackoverflow.com/a/1483959/233906
Cerber
6
Ele é possível a partir da versão 5.6.5, ver a resposta de Gustav abaixo (eu percebo a sua resposta foi publicado quando o MySQL ainda era 5.0!)
e2-e4
4
@ Kip, Oi, é possível ter um valor padrão para uma DATEcoluna? (não uma datetimecoluna).
Sajib Acharya 03/03
ti não parece ser possível para colunas DATA: você tem que usar DATETIME tipo de dados
Fabio Napodano
599

Na versão 5.6.5, é possível definir um valor padrão em uma coluna de data e hora e até criar uma coluna que será atualizada quando a linha for atualizada. A definição de tipo:

CREATE TABLE foo (
    `creation_time`     DATETIME DEFAULT CURRENT_TIMESTAMP,
    `modification_time` DATETIME ON UPDATE CURRENT_TIMESTAMP
)

Referência: http://optimize-this.blogspot.com/2012/04/datetime-default-now-finally-available.html

Gustav Bertram
fonte
3
Valor padrão inválido para 'menu_creation_time'
Fernando Trindade
2
@FernandoTrindade Você precisa do MySQL versão 5.6.5 ou posterior. Você pode vê-lo trabalhando aqui: sqlfiddle.com/#!9/dd2be
Gustav Bertram
1
@GustavBertram, estou usando a versão 5.6.22, mas ainda assim recebi o erro da seguinte forma: CREATE TABLE tbl (InsertDate DATETIME NÃO NULL PADRÃO CURRENT_TIMESTAMP, UpdateDate TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP (6)); Código de erro: 1294. Cláusula ON UPDATE inválida para a coluna 'UpdateDate'
Manish Sapkal
@ManishSapkal Você está usando um TIMESTAMP, não um DATETIME. Além disso, não torne NULL.
Gustav Bertram
1
Eu acho que a sintaxe "ON UPDATE" está errada. De acordo com dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html que deveria serdt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Dan Bough
148

O MySQL ( antes da versão 5.6.5 ) não permite que funções sejam usadas para os valores padrão de DateTime. O TIMESTAMP não é adequado devido ao seu comportamento estranho e não é recomendado para uso como dados de entrada. (Veja Padrões de tipo de dados MySQL .)

Dito isto, você pode fazer isso criando um gatilho .

Eu tenho uma tabela com um campo DateCreated do tipo DateTime. Eu criei um gatilho nessa tabela "Antes de inserir" e " SET NEW.DateCreated=NOW()" e funciona muito bem.

Espero que isso ajude alguém.

Stephan Unrau
fonte
21
CREATE TRIGGER trigger_foo_SetCreatedAt ANTES DE INSERIR NO FOO PARA CADA LINHA SET NEW.created_at = UTC_TIMESTAMP ();
kgriffs
5
Provavelmente, é melhor usar um carimbo de data e hora do que um gatilho para sanidade futura (manutenção). Este é um caso de uso trivial demais para um acionador, embora seja uma solução.
getWeberForStackExchange 7/11
8
Você provavelmente vai querer valor padrão aparelho sóIF NEW.created_at IS NOT NULL
Petr Peller
132

Para mim, a abordagem do gatilho funcionou melhor, mas eu encontrei um problema com a abordagem. Considere o gatilho básico para definir um campo de data para a hora atual na inserção:

CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
    FOR EACH ROW SET NEW.dateAdded = NOW();

Isso geralmente é ótimo, mas digamos que você queira definir o campo manualmente via instrução INSERT, da seguinte forma:

INSERT INTO tblMyTable(name, dateAdded) VALUES('Alice', '2010-01-03 04:30:43');

O que acontece é que o gatilho substitui imediatamente o valor fornecido para o campo e, portanto, a única maneira de definir um horário não atual é uma instrução UPDATE de acompanhamento - eca! Para substituir esse comportamento quando um valor é fornecido, tente esse gatilho ligeiramente modificado com o operador IFNULL:

CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
    FOR EACH ROW SET NEW.dateAdded = IFNULL(NEW.dateAdded, NOW());

Isso fornece o melhor dos dois mundos: você pode fornecer um valor para a coluna da data e ela será demorada; caso contrário, será padronizada para a hora atual. Ainda é um gueto relativo a algo limpo como DEFAULT GETDATE () na definição da tabela, mas estamos chegando mais perto!

John Larson
fonte
5
+1 por reconhecer a ressalva com a substituição de valores explícitos do usuário na inserção.
27411 Kip
2
Pessoalmente, acho que esse é o melhor caminho a percorrer. O TIMESTAMP realmente tem um comportamento estranho e eu nunca escreveria um código com uma limitação de 2038 anos.
Eric
Não importa, eu descobri. Esqueceu de definir o campo para permitir NULL. Não há mais avisos.
Kaji
Gatilhos são maus! Só use-os quando não houver outra maneira de fazer algo. É melhor atualizar para a ID 5.6.x do que usar um gatilho.
ksymeon
4
No MySQL 5.5, o IFNULL não funciona em DATETIME; usando o gatilho acima dateAdded, mostrará tudo '0000-00-00 00:00:00'. Usar isso faz o truque: `FOR EACH ROW IF NEW.dateAdded = 0 THEN SET NEW.dateAdded = NOW (); END IF; `
Kenney
28

Consegui resolver isso usando esta instrução alter na minha tabela que tinha dois campos de data e hora.

ALTER TABLE `test_table`
  CHANGE COLUMN `created_dt` `created_dt` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
  CHANGE COLUMN `updated_dt` `updated_dt` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

Isso funciona como você esperaria que a função now () funcionasse. Inserir nulos ou ignorar os campos created_dt e updated_dt resulta em um valor de carimbo de data e hora perfeito nos dois campos. Qualquer atualização na linha altera o updated_dt. Se você inserir registros através do navegador de consulta MySQL, precisará de mais uma etapa, um gatilho para manipular o created_dt com um novo carimbo de data / hora.

CREATE TRIGGER trig_test_table_insert BEFORE INSERT ON `test_table`
    FOR EACH ROW SET NEW.created_dt = NOW();

O gatilho pode ser o que você quiser, assim como a convenção de nomenclatura [trig] _ [my_table_name] _ [insert]

user188217
fonte
Eu quis dizer, se você inserir registros via navegador de consultas MySQL manualmente através da grade sem uma instrução insert (), o gatilho será necessário. Se você sempre usa uma instrução de inserção, o gatilho é completamente desnecessário.
Ops! Eu quis dizer O gatilho (nome) pode ser o que você quiser, porque o nome do gatilho não afeta a funcionalidade. A maioria das pessoas vai saber isso, mas algumas pessoas novas para MySQL pode não saber ...
Caramba, desculpe pela falta de quebras de linha. Use os pontos e vírgulas para marcar o final de cada linha.
24

Você pode usar gatilhos para fazer esse tipo de coisa.

CREATE TABLE `MyTable` (
`MyTable_ID`  int UNSIGNED NOT NULL AUTO_INCREMENT ,
`MyData`  varchar(10) NOT NULL ,
`CreationDate`  datetime NULL ,
`UpdateDate`  datetime NULL ,
PRIMARY KEY (`MyTable_ID`)
)
;

CREATE TRIGGER `MyTable_INSERT` BEFORE INSERT ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the creation date
    SET new.CreationDate = now();

        -- Set the udpate date
    Set new.UpdateDate = now();
END;

CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the udpate date
    Set new.UpdateDate = now();
END;
Donald
fonte
18

Para todos aqueles que perderam o coração tentando definir um valor DATETIME padrão no MySQL , eu sei exatamente como você se sente / se sentiu. Então aqui está é:

ALTER TABLE  `table_name` CHANGE `column_name` DATETIME NOT NULL DEFAULT 0

Observe cuidadosamente que não adicionei aspas simples / aspas duplas ao redor do 0

Eu estou literalmente pulando depois de resolver este: D

Augiwan
fonte
8
Não insere a hora não atual. Ele irá inserir '0000-00-00 00:00:00'.
Pit Digger
8
Eu não disse que define a hora atual. Muitas pessoas estavam / estão tentando definir um valor zero padrão, mas simplesmente não funciona. Precisamos eliminar as aspas. Como esse achado causou muito tempo e frustração, pensei em compartilhá-lo com a comunidade. Pessoas como você são responsáveis ​​por usuários que perdem o interesse em compartilhar informações úteis com outras pessoas. Eu seriamente não vejo nenhuma razão para obter um -1! Tanto faz.
Augiwan
3
O mesmo poderia ser alcançado com DATETIME NOT NULL.
Brendan Byrd
Há mais um caractere `dentro do comando sql de exemplo, que não consigo editar, pois é apenas uma edição de um caractere.
Quapka # 24/16
seu código não funcionava para mim, aqui é o que funcionouALTER TABLE zones MODIFY created datetime NOT NULL DEFAULT 0;
Smith
14

Se você já criou a tabela, poderá usar

Para alterar o valor padrão para a hora atual

ALTER TABLE <TABLE_NAME> 
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;

Para alterar o valor padrão para '2015-05-11 13:01:01'

ALTER TABLE <TABLE_NAME> 
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT '2015-05-11 13:01:01';
Saveendra Ekanayake
fonte
9

Estou executando o MySql Server 5.7.11 e esta frase:

ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '0000-00-00 00:00:00'

não está funcionando Mas o seguinte:

ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '1000-01-01 00:00:00'

simplesmente funciona .

Como nota de rodapé , ela é mencionada nos documentos do mysql :

O tipo DATE é usado para valores com uma parte da data, mas sem parte da hora. O MySQL recupera e exibe valores DATE no formato 'AAAA-MM-DD'. O intervalo suportado é de '1000-01-01' a '9999-12-31'.

mesmo se eles também disserem:

Valores inválidos de DATE, DATETIME ou TIMESTAMP são convertidos no valor “zero” do tipo apropriado ('0000-00-00' ou '0000-00-00 00:00:00').

Evhz
fonte
8

Você pode usar now () para definir o valor de uma coluna datetime, mas lembre-se de que não pode usá-lo como valor padrão.

KernelM
fonte
4
verdade. Eu apenas tentei usar agora e recebi o erro "Código de erro: 1067. Valor padrão inválido.". então qual é a resposta? ;-)
Brian Boatright
Esta é a melhor solução para comprometer as versões 5.5 e 5.6 do MySQL. Para a versão 5.5, pré-determine o valor NOW()e use-o posteriormente para a inserção. Para a versão 5.6, basta definir NOW()como o valor padrão.
Abel Callejo
8

Para todos os que usam a coluna TIMESTAMP como solução, quero destacar a seguinte limitação do manual:

http://dev.mysql.com/doc/refman/5.0/en/datetime.html

"O tipo de dados TIMESTAMP tem um intervalo de '1970-01-01 00:00:01' UTC a ' 2038-01-19 03:14:07 ' UTC. Possui propriedades variadas, dependendo da versão do MySQL e do SQL modo em que o servidor está sendo executado. Essas propriedades são descritas mais adiante nesta seção. "

Portanto, isso obviamente interromperá seu software em cerca de 28 anos.

Acredito que a única solução no lado do banco de dados é usar gatilhos, como mencionado em outras respostas.

Fabian
fonte
2
E se o MySQL fosse atualizado daqui a 20 anos e essa limitação fosse removida? Não tenho certeza se isso é possível, mas apenas um pensamento.
NessDan
7

Ao definir gatilhos de múltiplas linhas, é necessário alterar o delimitador, pois o ponto-e-vírgula será considerado pelo compilador MySQL como final do gatilho e gerará erro. por exemplo

DELIMITER //
CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the udpate date
    Set new.UpdateDate = now();
END//
DELIMITER ;
Drawin Kumar
fonte
5

Aqui está como fazê-lo no MySQL 5.1:

ALTER TABLE `table_name` CHANGE `column_name` `column_name` 
TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

Não faço idéia por que você deve digitar o nome da coluna duas vezes.

Samuel
fonte
5
CHANGE também é para renomear o campo. O nome da primeira coluna é o 'antigo', o segundo nome da coluna é o 'novo'. Parece redundante se você não estiver alterando o nome do campo. Se for muito esteticamente desagradável, tente MODIFY.
John Gordon
5

Embora não seja possível fazer isso DATETIMEna definição padrão, você pode simplesmente incorporar uma instrução select na sua instrução insert como esta:

INSERT INTO Yourtable (Field1, YourDateField) VALUES('val1', (select now()))

Observe a falta de aspas ao redor da mesa.

Para o MySQL 5.5

George
fonte
3

Se você está tentando definir o valor padrão como NOW (), não acho que o MySQL suporte isso. No MySQL, você não pode usar uma função ou expressão como o valor padrão para qualquer tipo de coluna, exceto a coluna do tipo de dados TIMESTAMP, para a qual você pode especificar o CURRENT_TIMESTAMP como padrão.

Vijesh VP
fonte
3

Eu acho simples no mysql, uma vez que o mysql é a função embutida chamada now (), que fornece o tempo atual (hora dessa inserção).

Portanto, sua consulta deve ser semelhante

CREATE TABLE defaultforTime(
    `creation_time`     DATETIME DEFAULT CURRENT_TIMESTAMP,
    `modification_time` DATETIME default now()
);

Obrigado.

Deepak N
fonte
2
CREATE TABLE `testtable` (
    `id` INT(10) NULL DEFAULT NULL,
    `colname` DATETIME NULL DEFAULT '1999-12-12 12:12:12'
)

Na consulta acima, para criar 'testtable', usei '1999-12-12 12:12:12' como valor padrão para a coluna DATETIME colname

Fathah Rehman P
fonte
1

Use o seguinte código

DELIMITER $$

    CREATE TRIGGER bu_table1_each BEFORE UPDATE ON table1 FOR EACH ROW
    BEGIN
      SET new.datefield = NOW();
    END $$

    DELIMITER ;
Rana Aalamgeer
fonte
0

Se você está tentando definir o valor padrão como NOW (), o MySQL suporta que você precise alterar o tipo dessa coluna TIMESTAMP em vez de DATETIME. TIMESTAMP tem data e hora atuais como padrão .. acho que resolverá o seu problema.

Dhrumil Shah
fonte
0

Tomemos, por exemplo, se eu tivesse uma tabela chamada 'site' com uma coluna created_at e update_at que eram DATETIME e precisam do valor padrão de agora, eu poderia executar o seguinte sql para conseguir isso.

ALTER TABLE `site` CHANGE` created_at` `created_at` TIMESTAMP NÃO NULL PADRÃO CURRENT_TIMESTAMP;

ALTER TABLE `site` CHANGE` created_at` `created_at` DATETIME NULL DEFAULT NULL;

ALTER TABLE `site` CHANGE` updated_at` `updated_at` TIMESTAMP NÃO NULL PADRÃO CURRENT_TIMESTAMP;

ALTER TABLE `site` CHANGE` updated_at` `updated_at` DATETIME NULL DEFAULT NULL;

A sequência de instruções é importante porque uma tabela não pode ter duas colunas do tipo TIMESTAMP com valores padrão de CUREENT TIMESTAMP

Joseph Persie
fonte
0

Este é o meu exemplo de gatilho:

/************ ROLE ************/
drop table if exists `role`;
create table `role` (
    `id_role` bigint(20) unsigned not null auto_increment,
    `date_created` datetime,
    `date_deleted` datetime,
    `name` varchar(35) not null,
    `description` text,
    primary key (`id_role`)
) comment='';

drop trigger if exists `role_date_created`;
create trigger `role_date_created` before insert
    on `role`
    for each row 
    set new.`date_created` = now();

Lucas Moyano Angelini
fonte
0

Trabalhando bem com o MySQL 8.x

CREATE TABLE `users` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `dateCreated` datetime DEFAULT CURRENT_TIMESTAMP,
      `dateUpdated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`),
      UNIQUE KEY `mobile_UNIQUE` (`mobile`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
Gvs Akhil
fonte
-3

Você pode resolver o carimbo de data / hora padrão. Primeiro, considere qual conjunto de caracteres você está usando, por exemplo, se você tirou utf8 desse conjunto de caracteres, suporta todos os idiomas e, se tirou o lat1, esse conjunto de caracteres suporta apenas o inglês. Próximo setp, se você estiver trabalhando em qualquer projeto, deve conhecer o fuso horário do cliente e selecionar você é o fuso do cliente. Esta etapa é obrigatória.

Srinivas
fonte
2
As colunas DateTime não podem ter valores padrão. Está documentado 'recurso'. Nem todos os desenvolvedores têm acesso para alterar a codificação de caracteres. E definir o servidor para o fuso horário de seus clientes geralmente não é uma possibilidade, especialmente quando os clientes não são todos nativos de uma única área de fuso horário.
Rb.usa # 21/10