2012-01-28 30 views
11

tengo que ser capaz de generar ejecutar una consulta que devolverá el siguiente valor de ID en la siguiente tabla:MySQL equivalente de SEQUENCE.NEXTVAL de Oracle

CREATE TABLE animals (
    id MEDIUMINT NOT NULL AUTO_INCREMENT, 
    name CHAR(30) NOT NULL, 
    PRIMARY KEY (id) 
) 

En Oracle puede llamar NEXTVAL en una secuencia y te da la siguiente secuencia (nota: sin tener que hacer una inserción en la mesa).

Tras Google torno He descubierto que se puede encontrar el valor actual de AUTO_INCREMENT usando la siguiente consulta:

SELECT Auto_increment 
FROM information_schema.tables 
WHERE table_name='animals'; 

El problema es me gustaría que el valor que se incrementará cada vez que se consulta el valor. En Oracle, cuando llama a nextval, el valor de la secuencia se incrementa incluso si no inserta una fila en una tabla.

¿Hay alguna manera de modificar la consulta anterior para que el valor devuelto sea siempre diferente de la última vez que se invocó la consulta? es decir, Autoincremento se incrementa cada vez que se comprueba y cuando se utiliza en una consulta, utilizará un nuevo valor.

Estoy usando Spring JDBCTemplate por lo que si se puede hacer en una consulta, mejor.

Respuesta

5

Este ejemplo demuestra InnoDB con una manera de poner en práctica su propio contador de uso de consultas entrelazados:

http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

¿Qué se necesita para crear un hueco para? Para reservar identificaciones? Prefiero "arreglar" el diseño a toda costa y actualizar los otros módulos en lugar de tocar una secuencia.

En lugar de simplemente incrementar la secuencia explícitamente, la implicaría insertando una fila predeterminada (marcada como no válida) para cada id. Para asignar y devolver la identificación. Este enfoque es consistente y portátil. Más tarde, en lugar de forzar inserciones utilizando un valor de secuencia explícito, puede actualizar estas filas predeterminadas por sus valores de secuencia coincidentes. Esto requiere más memoria pero no bloqueos. La recolección de basura en las filas expiradas puede ayudar aquí. las instrucciones 'insertar o actualizar' pueden volver a crear filas recogidas de basura, aunque no lo haría.

+0

a toda costa? De Verdad? –

4

Se podría añadir su propia función de MySQL - como se demostró en http://www.microshell.com/database/mysql/emulating-nextval-function-to-get-sequence-in-mysql/ - que le permite hacer algo como esto:

SELECT nextval('sq_my_sequence') as next_sequence; 
+0

vi ese ejemplo, mientras que buscando en Google. Desafortunadamente, es necesario eliminar el uso de AUTO_INCREMENT en la columna ID, lo que no es posible en este momento, ya que necesitaré cambiar otros módulos que usan esta tabla. Gracias. – ziggy

+1

En los comentarios en esa página alguien plantea la preocupación de que podría haber una condición de carrera. Parece más fácil utilizar el método auto_increment @Ivan dio, donde el trabajo se realiza en una sola declaración y, por lo tanto, es atómico. Podría envolver el método de Ivan en una función, lo que sería bueno, dándole lo mejor de ambos enfoques. –

+0

puede actualizar su respuesta para el contenido real en lugar de enlace? la consulta que proporcione solo no funcionará. – jangorecki

2

MySQL usa AUTO_INCREMENT que sirve a los propósitos. Sin embargo, hay diferencias a continuación:

MySQL a Oracle AUTO_INCREMENTSEQUENCE Diferencias

  • AUTO_INCREMENT se limita a una columna por tabla
  • AUTO_INCREMENT se debe asignar a un table.column específica (no permitir el uso de varias mesas)
  • AUTO_INCREMENT se inserta como una columna no se especifica, o un valor NULL

si le gustaría que se La implementación de SEQUENCE con MySQL se puede hacer con SP.

Consulte a continuación el enlace explicado todo lo que desea.

http://ronaldbradford.com/blog/sequences-in-mysql-2006-01-26/

1

desea que el siguiente valor en esa mesa para que pueda hacer filas que aún no se inserta sin molestar a otros procesos que están usando el incremento automático?

Algunas opciones:

seguir adelante y sólo tiene que insertar las filas de "agotar la secuencia", marcarlos como pendiente y luego actualizar más tarde.

Inserte en una transacción y cancele la transacción - la secuencia del número automático se debe agotar y hacer un "espacio" en la tabla normalmente - ese número ahora es libre de usar.

Con Oracle, la secuencia es completamente independiente de la tabla, por lo que los procesos pueden usar la secuencia o no (y también pueden usar la misma secuencia para diferentes tablas).En ese sentido, puede implementar una tabla de secuencia única a la que accede a través de algún tipo de función, y para los demás procesos que necesitan depender del autoincremento, elimine el autoincremento y use un desencadenador que lo asigne desde el mismo función de secuencia si no se proporciona una identificación.

10

http://docs.oracle.com/cd/E17952_01/refman-5.5-en/example-auto-increment.html

3.6.9. Utilización de AUTO_INCREMENT

El atributo AUTO_INCREMENT puede utilizarse para generar una identidad única para nuevas filas:

CREATE TABLE animals (
    id MEDIUMINT NOT NULL AUTO_INCREMENT, 
    name CHAR(30) NOT NULL, 
    PRIMARY KEY (id) 
); 

INSERT INTO animals (name) VALUES 
    ('dog'),('cat'),('penguin'), 
    ('lax'),('whale'),('ostrich'); 

SELECT * FROM animals; 
Which returns: 

+----+---------+ 
| id | name | 
+----+---------+ 
| 1 | dog  | 
| 2 | cat  | 
| 3 | penguin | 
| 4 | lax  | 
| 5 | whale | 
| 6 | ostrich | 
+----+---------+ 

No valor se ha especificado para la columna AUTO_INCREMENT, por lo MySQL asigna números de secuencia de forma automática. También puede asignar explícitamente NULL o 0 a la columna para generar números de secuencia.

Puede recuperar el valor AUTO_INCREMENT más reciente con la función SQL LAST_INSERT_ID() o la función de la API C de mysql_insert_id(). Estas funciones son específicas de la conexión, por lo que sus valores de retorno no se ven afectados por otra conexión que también realiza inserciones.

Utilice el tipo de datos entero más pequeño para la columna AUTO_INCREMENT que sea lo suficientemente grande como para mantener el valor máximo de secuencia que necesitará. Cuando la columna alcanza el límite superior del tipo de datos, el próximo intento de generar un número de secuencia falla. Utilice el atributo UNSIGNED si es posible para permitir un rango mayor. Por ejemplo, si usa TINYINT, el número máximo de secuencia permisible es 127. Para TINYINT UNSIGNED, el máximo es 255. Consulte la Sección 11.2.1, "Tipos enteros (valor exacto) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT "Para los rangos de todos los tipos de enteros.

Nota Para una inserción de varias filas, LAST_INSERT_ID() y mysql_insert_id() realmente devuelven la clave AUTO_INCREMENT de la primera de las filas insertadas. Esto permite que las inserciones de múltiples filas se reproduzcan correctamente en otros servidores en una configuración de replicación.

Si la columna AUTO_INCREMENT es parte de índices múltiples, MySQL genera valores de secuencia usando el índice que comienza con la columna AUTO_INCREMENT, si hay uno. Por ejemplo, si la tabla de animales contenía índices PRIMARY KEY (grp, id) e INDEX (id), MySQL ignoraría la PRIMARY KEY para generar valores de secuencia. Como resultado, la tabla contendría una secuencia única, no una secuencia por valor de grp.

Para empezar con un valor AUTO_INCREMENT distinto de 1, establece que el valor con CREATE TABLE o ALTER TABLE, así:

mysql> ALTER TABLE TBL AUTO_INCREMENT = 100; InnoDB Notes

Para tablas InnoDB, tenga cuidado si modifica la columna que contiene el valor de autoincremento en el medio de una secuencia de instrucciones INSERT. Por ejemplo, si usa una instrucción UPDATE para poner un nuevo valor mayor en la columna de incremento automático, un INSERT posterior podría encontrar un error de "Duplicar entrada". La prueba de si un valor de autoincremento ya está presente ocurre si realiza un DELETE seguido de más instrucciones INSERT, o cuando COMPROMETE la transacción, pero no después de una instrucción UPDATE.

MyISAM Notas

Para tablas MyISAM, puede especificar AUTO_INCREMENT en una columna secundaria en un índice de múltiples columnas. En este caso, el valor generado para la columna AUTO_INCREMENT se calcula como MAX (auto_increment_column) + 1 WHERE prefix = given-prefix. Esto es útil cuando desea colocar datos en grupos ordenados.

CREATE TABLE animals (
    grp ENUM('fish','mammal','bird') NOT NULL, 
    id MEDIUMINT NOT NULL AUTO_INCREMENT, 
    name CHAR(30) NOT NULL, 
    PRIMARY KEY (grp,id) 
) ENGINE=MyISAM; 

INSERT INTO animals (grp,name) VALUES 
    ('mammal','dog'),('mammal','cat'), 
    ('bird','penguin'),('fish','lax'),('mammal','whale'), 
    ('bird','ostrich'); 

SELECT * FROM animals ORDER BY grp,id; 
Which returns: 

+--------+----+---------+ 
| grp | id | name | 
+--------+----+---------+ 
| fish | 1 | lax  | 
| mammal | 1 | dog  | 
| mammal | 2 | cat  | 
| mammal | 3 | whale | 
| bird | 1 | penguin | 
| bird | 2 | ostrich | 
+--------+----+---------+ 

En este caso (cuando la columna AUTO_INCREMENT es parte de un índice de múltiples columnas), los valores AUTO_INCREMENT son reutilizados si se elimina la fila con el valor AUTO_INCREMENT más grande de cualquier grupo. Esto sucede incluso para las tablas MyISAM, cuyos valores de AUTO_INCREMENT normalmente no se vuelven a utilizar.

Lectura adicional

Más información sobre AUTO_INCREMENT está disponible aquí:

cómo asignar el atributo AUTO_INCREMENT a una columna: Sección 13.1.17, “CREATE tabla de sintaxis” y Sección 13.1.7, “ ALTER TABLE Sintaxis ".

Cómo se comporta AUTO_INCREMENT según el modo SQL NO_AUTO_VALUE_ON_ZERO: Sección 5.1.7, "Modos SQL del servidor".

Cómo usar la función LAST_INSERT_ID() para encontrar la fila que contiene el valor más reciente de AUTO_INCREMENT: Sección 12.14, "Funciones de información".

Configuración del valor AUTO_INCREMENT que se utilizará: Sección 5.1.4, "Variables del sistema del servidor".

AUTO_INCREMENTO y replicación: Sección 16.4.1.1, "Replicación y AUTO_INCREMENTO".

Variables del sistema de servidor relacionadas con AUTO_INCREMENT (auto_increment_increment y auto_increment_offset) que se pueden usar para la replicación: Sección 5.1.4, "Variables del sistema del servidor".

http://search.oracle.com/search/search?q=auto_increment&group=Documentation&x=0&y=0

0

Tenga una mirada en MariaDBs SEQUENCE motor.Con él se puede generar secuencias tan fácil como

SELECT seq FROM seq_1_to_5; 
+-----+ 
| seq | 
+-----+ 
| 1 | 
| 2 | 
| 3 | 
| 4 | 
| 5 | 
+-----+ 

detalles here: https://mariadb.com/kb/en/mariadb/sequence/

Con esto, usted debe ser capaz de hacer algo como

SELECT min(seq) as nextVal FROM seq_1_to_500 
WHERE seq NOT IN (SELECT ID FROM customers) 
+0

Algo interesante, pero probablemente no sea una respuesta a la pregunta. – hgoebl

Cuestiones relacionadas