web-dev-qa-db-fra.com

Insérer et définir la valeur avec max () + 1 problèmes

J'essaie d'insérer une nouvelle ligne et de définir le customer_id avec max () + 1. La raison en est que la table a déjà un auto_increatment sur une autre colonne nommée id et que la table aura plusieurs lignes avec le même customer_id.

Avec ça:

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id ) FROM customers) +1, 'jim', 'sock')

... Je continue à avoir l'erreur suivante:

#1093 - You can't specify target table 'customers' for update in FROM clause

Aussi, comment puis-je empêcher 2 clients différents d'être ajoutés en même temps et de ne pas avoir le même customer_id?

36
Cozzy

Corrigez, vous ne pouvez pas modifier et sélectionner dans la même table dans la même requête. Vous devrez effectuer les opérations ci-dessus dans deux requêtes distinctes. 

Le meilleur moyen consiste à utiliser une transaction, mais si vous n'utilisez pas de tables innodb, le mieux est de verrouiller les tables puis d'exécuter vos requêtes. Alors:

Lock tables customers write;

$max = SELECT MAX( customer_id ) FROM customers;

Prenez le max id puis effectuez l'insertion

INSERT INTO customers( customer_id, firstname, surname )
VALUES ($max+1 , 'jim', 'sock')

unlock tables;
25
RDL

Vous pouvez utiliser l'instruction INSERT ... SELECT pour obtenir la valeur MAX()+1 et insérer en même temps:

INSERT INTO 
customers( customer_id, firstname, surname )
SELECT MAX( customer_id ) + 1, 'jim', 'sock' FROM customers;

Remarque: Vous devez supprimer la VALUES de votre INSERT et vous assurer que les champs SELECT sélectionnés correspondent aux champs déclarés INSERT.

65
EmCo

Utilisez un nom d'alias pour la requête interne comme ceci

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id )+1 FROM customers cust), 'sharath', 'rock')
9
Sharath Nadig
insert into table1(id1) select (max(id1)+1) from table1;
6
test

SELECT MAX(col) +1 n'est pas sûr - cela ne garantit pas que vous n'insérez pas plus d'un client avec la même valeur customer_id, que vous sélectionniez dans la même table ou dans une autre. Le le moyen approprié de s'assurer qu'une valeur entière unique est assignée lors de l'insertion dans votre table dans MySQL consiste à utiliser AUTO_INCREMENT . La norme ANSI consiste à utiliser des séquences, mais MySQL ne les prend pas en charge. Une colonne AUTO_INCREMENT ne peut être définie que dans l'instruction CREATE TABLE:

CREATE TABLE `customers` (
  `customer_id` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(45) DEFAULT NULL,
  `surname` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`customer_id`)
)

Cela dit, cela a bien fonctionné pour moi le 5.1.49:

CREATE TABLE `customers` (
  `customer_id` int(11) NOT NULL DEFAULT '0',
  `firstname` varchar(45) DEFAULT NULL,
  `surname` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$

INSERT INTO customers VALUES (1, 'a', 'b');

INSERT INTO customers 
SELECT MAX(customer_id) + 1, 'jim', 'sock'
  FROM CUSTOMERS;
5
OMG Ponies

Utilisez un alias de table dans la sous-requête:

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id ) FROM customers C) +1, 'jim', 'sock')
3

Vous ne pouvez pas le faire en une seule requête, mais vous pouvez le faire dans une transaction. Effectuez la première sélection MAX () et verrouillez la table, puis effectuez l'insertion. La transaction garantit que rien ne va interrompre les deux requêtes et le verrou garantit que rien d'autre ne peut essayer de faire la même chose ailleurs au même moment.

1
Marc B

Aucune des réponses à propos ne fonctionne pour mon cas. J'ai eu la réponse de ici , et mon SQL est:

INSERT INTO product (id, catalog_id, status_id, name, measure_unit_id, description, create_time)
VALUES (
  (SELECT id FROM (SELECT COALESCE(MAX(id),0)+1 AS id FROM product) AS temp),
  (SELECT id FROM product_catalog WHERE name="AppSys1"),
  (SELECT id FROM product_status WHERE name ="active"),
  "prod_name_x",
  (SELECT id FROM measure_unit WHERE name ="unit"),
  "prod_description_y",
  UNIX_TIMESTAMP(NOW())
)
1
zipper

Nous déclarons une variable 'a'

SET **@a** = (SELECT MAX( customer_id ) FROM customers) +1;

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  (**@a**, 'jim', 'sock')
0
Alex Shel

Le mien est un insert, mais voici ce que j'ai fini par utiliser les suggestions ici.

update
   m
set
   m.Host_id = max(h.Host_id)
from
   t_po_master as m
   inner join t_al_Host_po_master as h on m.po_number = h.po_number
where
   m.Host_id is NULL
   and m.client_code = '01'

EDIT - Cela n'a pas fonctionné. Je ne sais pas pourquoi, car le transformer en une instruction de sélection semble indiquer que cela fonctionnerait, mais cela a mis à jour tous les Host_ids avec le même identifiant. Donc, je ne voudrais pas utiliser ceci est un bon exemple.

0
silverbow25