2012-06-22 13 views
5

Teniendo en cuenta esto:partición MySQL con UNIX_TIMESTAMP partir de una variable

delimiter // 
create procedure setup() 
begin 
    declare d datetime; 
    set d = rounddate(now()); 

    create table s_time (req_id int not null, 
         ser_id int not null, 
         hel_id int not null, 
         posted int unsigned not null, 
         completed int unsigned not null default 0 
        ) 
    partition by range (completed) (partition p0 values less than (unix_timestamp(d)), 
            partition p1 values less than (unix_timestamp(d + interval 1 day)) 
           ); 
end// 

me sale:

ERROR 1064 (42000) : Constant, random, or timezone-dependent expression in (sub)partitioning function are not allowed

¿Hay alguna manera de conseguir que esto funcione, o tengo que utilizar un hardware cadena codificada para la entrada. es decir, use: unix_timestamp('2012-07-07 00:00:00')

+0

¿Se supone que su tabla 's_time' sobrevivirá al final de su procedimiento? Además, ¿espera que las particiones se reorganicen de manera automática? En otras palabras: ahora mismo, la partición 'p0' contiene todos los registros hasta ahora. En 24 horas a partir de ahora, ¿se espera que 'p0' contenga todos los registros hasta" en 24 horas a partir de ahora "? – RandomSeed

+0

Este procedimiento es solo para configurar automáticamente la tabla. La tabla se usará como una partición progresiva. Después de 24 horas, se eliminará la primera partición y se agregará otra. Me preguntaba si hay una forma de no codificar las dos primeras particiones. Supongo que podría hacer otro procedimiento que haga las primeras dos tiradas iniciales y llamar después de la creación de la tabla con valores codificados. –

Respuesta

5

Para mantener la solución en sql completo esto es lo que he encontrado.

delimiter // 
create procedure setup() 
begin 
    declare d, d2 int; 
    set d = unix_timestamp(); 
    set d2 = unix_timestamp(now() + interval 1 day); 

    create table s_time (req_id int not null, 
         ser_id int not null, 
         hel_id int not null, 
         posted int unsigned not null, 
         completed int unsigned not null default 0 
        ); 

    SET @stmt = concat('alter table s_time PARTITION BY RANGE (completed) (
         partition p0 values less than (', d, '), 
         partition p1 values less than (', d2, '))'); 
    PREPARE pStmt FROM @stmt; 
    EXECUTE pStmt; 
    DEALLOCATE PREPARE pStmt; 

end// 
delimiter ; 
call setup(); 
2

El motivo de que esto no funcione no es tan claro, sospecho que hay un error en la documentación o en el mensaje de error. El error que está recibiendo es inapropiado, en mi opinión.

Según the manual:

Los siguientes constructos no están permitidos en la partición expresiones:

  • procedimientos almacenados, funciones almacenados, UDF, o plugins.
  • Variables declaradas o variables de usuario.

Esto explica por qué falla la definición de su tabla.

Ahora, ¿cómo deshacerse de su variable? Si intenta eliminar la variable declarada de la definición de partición:

CREATE TABLE s_time (
    completed INT UNSIGNED NOT NULL DEFAULT 0 
) 
PARTITION BY RANGE (completed ) (
    PARTITION p0 VALUES LESS THAN (UNIX_TIMESTAMP()) 
); 

obtendrá el mismo error. Sin embargo, el MySQL manual afirma:

También es posible utilizar una expresión en valores por debajo de cláusulas. Sin embargo, MySQL debe poder evaluar el valor de retorno de la expresión como parte de una comparación MENOS DE (<).

De acuerdo con esta definición, UNIX_TIMESTAMP() debe ser una expresión válida. Esta oración del manual es inexacta por decir lo menos. Tengo mucha curiosidad por ver si alguien más puede proporcionar otro entendimiento.

Ahora, mirando el mensaje de error, si se tiene en cuenta la cláusula LESS THAN como parte de la "función de partición", a continuación, el mensaje de error empieza a tener sentido:

ERROR 1064 (42000): Constante, azar o la zona horaria dependiente de expresión en (sub) función partición o en menos de cláusula no están permitidos

Por "aleatorio", también significan no determinista, que la función UNIX_TIMESTAMP() es por definición.

Para lograr lo que está tratando de hacer, no veo otra solución sino usar una secuencia de comandos externa para generar el comando ALTER TABLE adecuado.

1) Crea tu tabla inicial:

CREATE TABLE s_time (
    req_id INT NOT NULL, 
    ser_id INT NOT NULL, 
    hel_id INT NOT NULL, 
    posted INT UNSIGNED NOT NULL, 
    completed INT UNSIGNED NOT NULL DEFAULT 0 
) PARTITION BY RANGE (completed) (
    PARTITION p0 VALUES LESS THAN (0), 
    PARTITION p1 VALUES LESS THAN (1) 
); 

2) Reorganise the partitions de vez en cuando (por ejemplo con PHP):

<?php 
    $query = 
     "ALTER TABLE s_time REORGANIZE PARTITION p0, p1 INTO (
      PARTITION p0 VALUES LESS THAN ($today), 
      PARTITION p1 VALUES LESS THAN ($tomorrow) 
     )"; 

Véase el proof of concept here.

Cuestiones relacionadas