2012-06-22 36 views
5

Với này:phân vùng mysql với unix_timestamp từ biến

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// 

tôi nhận được:

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

Có cách nào để có được điều này để làm việc, hay tôi phải sử dụng một hard- chuỗi được mã hóa cho đầu vào. tức là sử dụng: unix_timestamp('2012-07-07 00:00:00')

+0

Bảng 's_time' của bạn có thể tồn tại khi kết thúc thủ tục không? Ngoài ra, bạn đang mong đợi các phân vùng được tổ chức lại một cách tự nhiên? Nói cách khác: ngay bây giờ, phân vùng 'p0' chứa tất cả các bản ghi lên đến ngay bây giờ. Trong 24hs từ bây giờ, sẽ 'p0' được dự kiến ​​sẽ chứa tất cả hồ sơ lên ​​đến" trong 24 giờ từ bây giờ "? – RandomSeed

+0

Thủ tục này chỉ để tự động thiết lập bảng. Bảng sẽ được sử dụng như một phân vùng lăn. Sau 24 giờ phân vùng đầu tiên sẽ bị xóa và một phân vùng khác sẽ được thêm vào. Tôi đã tự hỏi liệu có cách nào không mã hóa hai phân vùng đầu tiên không. Tôi đoán tôi có thể thực hiện một thủ tục khác mà thực hiện hai cuộn đầu tiên và gọi sau khi tạo bảng với các giá trị được mã hóa cứng. –

Trả lời

5

Để giữ cho giải pháp trong sql đầy đủ này là những gì tôi đã tìm thấy.

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

Lý do không hoạt động này không rõ ràng, tôi nghi ngờ có lỗi trong tài liệu hoặc trong thông báo lỗi. Lỗi bạn nhận được là không phù hợp, theo ý kiến ​​của tôi.

Theo the manual:

Các cấu trúc sau đây không được phép trong phân vùng biểu:

  • thủ tục lưu trữ, chức năng lưu trữ, UDFs hoặc plugin.
  • Biến được khai báo hoặc biến người dùng.

Điều này giải thích tại sao định nghĩa bảng của bạn không thành công.

Bây giờ, làm thế nào để loại bỏ biến của bạn? Nếu bạn cố gắng xóa biến đã khai báo khỏi định nghĩa phân vùng:

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

bạn sẽ gặp lỗi tương tự. Tuy nhiên, các trạng thái MySQL manual:

Cũng có thể sử dụng cụm từ trong mệnh đề VALUES LESS THAN. Tuy nhiên, MySQL phải có khả năng đánh giá giá trị trả lại của biểu thức như là một phần của một LESS THAN (<) so sánh.

Theo định nghĩa này, UNIX_TIMESTAMP() phải là biểu thức hợp lệ. Câu này từ hướng dẫn là không chính xác để nói rằng ít nhất. Tôi rất tò mò muốn xem liệu người khác có thể cung cấp một sự hiểu biết khác không.

Bây giờ, nhìn vào các thông báo lỗi, nếu bạn xem xét các khoản LESS THAN như một phần của "chức năng phân vùng", sau đó được thông báo lỗi bắt đầu làm cho ý nghĩa:

ERROR 1064 (42000): Constant, ngẫu nhiên, hoặc múi giờ phụ thuộc vào biểu hiện trong (sub) phân vùng chức năng hoặc trong dƯỚI khoản không được phép

Bằng cách "ngẫu nhiên", họ cũng có nghĩa không xác định, mà chức năng UNIX_TIMESTAMP() là theo định nghĩa.

Để đạt được những gì bạn đang cố gắng làm, tôi không thấy giải pháp nào khác ngoài việc sử dụng tập lệnh bên ngoài để tạo lệnh ALTER TABLE phù hợp.

1) Tạo bảng đầu tiên của bạn:

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 tất cả bây giờ và sau đó (ví dụ: với PHP):

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

Xem proof of concept here.

Các vấn đề liên quan