Given this :
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//
I get :
ERROR 1064 (42000) : Constant, random, or timezone-dependent expression in (sub)partitioning function are not allowed
Is there any way to get this to work, or do I have to use a hard-coded string for the input. ie use : unix_timestamp('2012-07-07 00:00:00')
To keep the solution in full sql this is what I have found.
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();
The reason of this not working is not so clear, I suspect a bug either in the documentation or in the error message. The error you are receiving is inappropriate, in my opinion.
According to the manual:
The following constructs are not permitted in partitioning expressions:
- Stored procedures, stored functions, UDFs, or plugins.
- Declared variables or user variables.
This explains why your table definition fails.
Now, how to get rid of your variable? If you try to remove the declared variable from the partition definition:
CREATE TABLE s_time (
completed INT UNSIGNED NOT NULL DEFAULT 0
)
PARTITION BY RANGE ( completed ) (
PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP() )
);
you will get the same error. However, the MySQL manual states:
It is also possible to use an expression in VALUES LESS THAN clauses. However, MySQL must be able to evaluate the expression's return value as part of a LESS THAN (<) comparison.
According to this definition, UNIX_TIMESTAMP()
should be a valid expression. This sentence from the manual is inaccurate to say the least. I am very curious to see if someone else could provide another understanding.
Now, looking at the error message, if you consider the LESS THAN
clause as a part of the "partitioning function", then the error message starts making sense:
ERROR 1064 (42000) : Constant, random, or timezone-dependent expression in (sub)partitioning function or in LESS THAN clause are not allowed
By "random", they also mean non-deterministic, which the UNIX_TIMESTAMP()
function is by definition.
To achieve what you are trying to do, I see no other solution but using an external script to generate the suitable ALTER TABLE
command.
1) Create your initial table:
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 every now and then (e.g. with PHP):
<?php
$query =
"ALTER TABLE s_time REORGANIZE PARTITION p0, p1 INTO (
PARTITION p0 VALUES LESS THAN ($today),
PARTITION p1 VALUES LESS THAN ($tomorrow)
)";
See the proof of concept here.
来源:https://stackoverflow.com/questions/11163237/mysql-partitioning-with-unix-timestamp-from-variable