Pergunta

Eu gostaria de ter um gatilho para executar a operação seguinte para registros inseridos:

 # pseudocode
 if new.group_id is null
    set new.group_id = new.id
 else
    # don't touch it
 end

Mais claramente: diga que tenho uma tabela com três colunas: id chave primária, group_id int, value Varchar.

Quando eu insiro com group_id Curtiu isso:

INSERT INTO table(value, group_id) VALUES ('a', 10)

Eu gostaria de ter:

id | group_id | value
---+----------+------
 1 |       10 | a

Mas quando eu omito group_id:

INSERT INTO table(value) VALUES ('b')

deve ser definido automaticamente para o id deste registro:

id | group_id | value
---+----------+------
 2 |        2 | b

É possível com um gatilho? (Eu sei que posso atualizar o registro depois de inserir, mas ter o gatilho seria melhor.)

Foi útil?

Solução

Não conheço nenhuma maneira de fazer isso em uma declaração, mesmo usando um gatilho.

A solução de gatilho que @lucky sugeriu que seria assim em MySQL:

CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
  SET NEW.group_id = COALESCE(NEW.group_id, NEW.id);
END

No entanto, há um problema. No BEFORE INSERT fase, a gerada automática id O valor ainda não foi gerado. Então se group_id é nulo, padroniza para NEW.id que é sempre 0.

Mas se você mudar esse gatilho para disparar durante o AFTER INSERT fase, então você tem acesso ao valor gerado de NEW.id, você não pode modificar os valores da coluna.

MySQL não suporta expressões para o DEFAULT de uma coluna, para que você não possa declarar esse comportamento na definição da tabela.

A única solução é fazer o INSERT, e então imediatamente faça um UPDATE Para mudar o group_id Se não estiver definido.

INSERT INTO MyTable (group_id, value) VALUES (NULL, 'a');
UPDATE MyTable SET group_id = COALESCE(group_id, id) WHERE id = LAST_INSERT_ID();

Outras dicas

Estou respondendo aqui, como na resposta aceita Bill Karwin estados:

Na fase anterior, o valor de ID gerado automaticamente ainda não foi gerado. Portanto, se Group_Id for nulo, ele padrão é o novo.id, que é sempre 0.


Eu tenho uma resposta para isso - para OP (e os visitantes que virão), aqui estão poucos pontos: você não pode atualizar a tabela de onde o gatilho é invocado, pois você ficar Erro 1442:

Error Code: 1442
Can't update table 'MyTable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

1. Para atualizar a nova linhaUsar BEFORE INSERT ON Trigger, dessa maneira você pode atualizar todos os campos para a nova linha, que pode ser acessível através do novo operador, ou seja,

set NEW.group_id = NEW.id

2. Get Auto_INCrement Value antes da inserção:

SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='MyTable'

Para resumir - o gatilho SQL para 'D Be algo como seguinte:

DELIMITER //
DROP TRIGGER IF EXISTS MyTrigger//
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
    IF new.group_id IS NULL
        set @auto_id := (SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES
                         WHERE TABLE_NAME='MyTable' AND TABLE_SCHEMA=DATABASE() ); 
        set NEW.group_id = @auto_id;
    ENF IF;
END;
//
DELIMITER ;

Isso funciona para mim

DELIMITER $$
CREATE TRIGGER `myTriggerNameHere`
BEFORE INSERT ON `table` FOR EACH ROW
BEGIN
    SET NEW.group_id = IF(NEW.group_id IS NULL, LAST_INSERT_ID()+1, NEW.group_id);
END;
$$
DELIMITER ;

Eu acredito que isso vai funcionar para você

Eu tenho duas mesas

test_b: a_id, value
test_c: a_id, value

E aqui está um gatilho na inserção do teste b. Ele verifica se A_ID é nulo e se for insere 0

CREATE TRIGGER test_b AFTER INSERT ON test_b
  FOR EACH ROW 
    INSERT INTO test_c (a_id, value) VALUES (IFNULL(NEW.a_id, 0),NEW.value)

Esse gatilho deve fazer o que você pediu.

   CREATE TRIGGER mytrigger BEFORE INSERT ON mytable
          IF new.group_id IS NULL
            SET new.group_id = new.id
          END IF
      END;

É copiado de um exemplo muito semelhante no Documentação do MySQL página.

Um gatilho parece um exagero nessa situação. Basta aplicar um padrão.

CREATE TABLE `test` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `value` varchar(100) NOT NULL,
    `group_id` TINYINT(3) UNSIGNED NOT NULL DEFAULT '2'
)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top