2012-02-11 10 views
6

Tôi có một tập lệnh mà tôi sử dụng để xây dựng cả bảng và thủ tục được lưu trữ. Ví dụ: tôi có một cột thuộc loại varchar. varchar yêu cầu tham số kích thước, kích thước đó tôi cũng sử dụng làm tham số trong các thủ tục được lưu trữ và trong các quy trình đó.Các tập lệnh SQL - Có tương đương với #define tồn tại không?

là nó có thể có thequivalentnt của #define cho kích thước của nó, vì vậy tôi có thể dễ dàng điều chỉnh kích thước mà không cần phải thay đổi ithroughht toàn bộ kịch bản?

Tôi đang sử dụng bàn làm việc MySql.

EDIT

Tôi đã thử SETDECLARE

Tôi có một kịch bản - đây là (rút gọn)

CREATE TABLE `locations` 
(
    `location` VARCHAR(25)  NOT NULL 
); 

... 
CREATE PROCEDURE AddLocation (IN location VARCHAR(25) 
BEGIN 
... 
END$$ 

Những gì tôi đang cố gắng để đạt được là thay thế các giá trị 25 trong tập lệnh có hằng số - tương tự như #define ở đầu tập lệnh tạo bảng và được lưu trữ thủ tục, vì vậy tôi có thể dễ dàng thay đổi số 25 thành một số khác.

Bất kỳ ai đã tìm thấy giải pháp cho vấn đề này?

+0

khai báo? http://dev.mysql.com/doc/refman/5.0/en/declare-local-variable.html –

+0

Tôi đã viết một số SW để làm một điều như vậy - nó là miễn phí và nó ở đây http: // mysql-pre- processor.batcave.net/. Chỉ cần đặt một vài thứ vào xô của tổ chức từ thiện của sự lựa chọn của bạn –

Trả lời

18

C Pre Processor (cpp) là lịch sử gắn liền với C (vì vậy tên), nhưng nó thực sự là một bộ xử lý văn bản chung mà có thể được sử dụng (hoặc bị lạm dụng) cho cái gì khác.

Hãy xem tệp này, có tên location.src (xem thêm về sau).

// C++ style comments works here 
/* C style works also */ 
-- plain old SQL comments also work, 
-- but you should avoid using '#' style of comments, 
-- this will confuse the C pre-processor ... 

#define LOCATION_LEN 25 

/* Debug helper macro */ 
#include "debug.src" 

DROP TABLE IF EXISTS test.locations; 
CREATE TABLE test.locations 
(
    `location` VARCHAR(LOCATION_LEN) NOT NULL 
); 

DROP PROCEDURE IF EXISTS test.AddLocation; 
delimiter $$ 
CREATE PROCEDURE test.AddLocation (IN location VARCHAR(LOCATION_LEN)) 
BEGIN 
    -- example of macro 
    ASSERT(length(location) > 0, "lost or something ?"); 

    -- do something 
    select "Hi there."; 
END 
$$ 

delimiter ; 

và tập tin debug.src, được bao gồm:

#ifdef HAVE_DEBUG 
#define ASSERT(C, T)           \ 
    begin              \ 
    if (not (C)) then           \ 
     begin             \ 
     declare my_msg varchar(1000);       \ 
     set my_msg = concat("Assert failed, file:", __FILE__, \ 
          ", line: ", __LINE__,    \ 
          ", condition ", #C,    \ 
          ", text: ", T);     \ 
     signal sqlstate "HY000" set message_text = my_msg; \ 
    end;              \ 
    end if;             \ 
    end 
#else 
#define ASSERT(C, T) begin end 
#endif 

Khi biên soạn với:

cpp -E location.src -o location.sql 

bạn lấy mã bạn đang tìm kiếm, với cpp mở rộng giá trị #define .

Khi biên soạn với:

cpp -E -DHAVE_DEBUG location.src -o location.sql 

bạn nhận được như nhau, cộng với vĩ mô ASSERT (được đăng như một phần thưởng, để hiển thị những gì thể được thực hiện).

Giả sử một xây dựng với HAVE_DEBUG triển khai trong một môi trường thử nghiệm (trong 5.5 hoặc mới hơn kể từ SIGNAL được sử dụng), kết quả sẽ như thế này:

mysql> call AddLocation("Here"); 
+-----------+ 
| Hi there. | 
+-----------+ 
| Hi there. | 
+-----------+ 
1 row in set (0.00 sec) 

Query OK, 0 rows affected (0.00 sec) 

mysql> call AddLocation(""); 
ERROR 1644 (HY000): Assert failed, file:location.src, line: 24, condition length(location) > 0, text: lost or something ? 

Lưu ý cách tên tập tin, số dòng, và các điểm điều kiện ngay tại vị trí trong mã nguồn trong location.src, nơi khẳng định được nâng lên, cảm ơn một lần nữa đến bộ xử lý trước C.

Bây giờ, về phần mở rộng ".src" file:

  • bạn có thể sử dụng bất cứ điều gì.
  • Có một phần mở rộng tệp khác sẽ giúp với các tệp makefiles, v.v. và ngăn sự nhầm lẫn.

EDIT: Được đăng dưới dạng .xql, được đổi tên thành .src để làm rõ. Không có gì liên quan đến truy vấn xml tại đây.

Như với bất kỳ công cụ nào, sử dụng cpp có thể dẫn đến những điều tốt đẹp và trường hợp sử dụng để duy trì LOCATION_LEN theo cách di động có vẻ rất hợp lý. Nó cũng có thể dẫn đến những điều xấu, với quá nhiều #include, lồng nhau #ifdef địa ngục, macro, vv mà ở cuối obfuscate mã, do đó, mileage của bạn có thể khác nhau.

Với câu trả lời này, bạn sẽ có được toàn bộ điều (#define, #include, #ifdef, __FILE__, __LINE__, #C, tùy chọn dòng lệnh để xây dựng), vì vậy tôi hy vọng nó nên bao gồm tất cả.

+4

khéo léo.Tôi chưa bao giờ nghĩ đến việc sử dụng một bộ xử lý trước trên các tệp SQL. – njr101

+0

Tôi đã hy vọng cho một giải pháp mà không yêu cầu sử dụng một bộ tiền xử lý. Nhưng tôi sẽ khám phá tùy chọn này. –

1

Bạn đã thử SET chưa?

đây là một ví dụ:

SET @var_name = expr 

nhiều ví dụ ở đây: http://dev.mysql.com/doc/refman/5.0/en/user-variables.html

+0

Tôi đã thử cả hai tuyên bố và thiết lập. Chỉ muốn đặt ở đầu kịch bản các kích thước cho các trường khác nhau. Phần còn lại của kịch bản lệnh để tạo các bảng/khung nhìn/các thủ tục/hàm được lưu trữ dựa trên các giá trị đó. Chỉ để làm cho việc xây dựng lại cơ sở dữ liệu trở nên dễ dàng hơn với các kích cỡ khác nhau của các trường khác nhau. –

+0

Ah ... có lẽ bạn muốn đọc http://stackoverflow.com/questions/1009954/mysql-variable-vs-variable-whats-the-difference này và bạn có thể gán một biến toàn cầu với 'SET' http://dev.mysql.com/doc/refman/5.1/en/set-option.html –

1

Có vẻ như bạn đang tìm kiếm cho người dùng định nghĩa các kiểu dữ liệu. Thật không may cho tất cả chúng tôi mySQL chưa hỗ trợ người dùng định nghĩa các loại dữ liệu như SQL Server, Oracle, và những người khác làm.

Dưới đây là danh sách các kiểu dữ liệu được hỗ trợ: http://dev.mysql.com/doc/refman/5.0/en/data-types.html

0

Đối với những người quan tâm:

tôi đã kết thúc viết một kịch bản PHP vì:

a) Các máy có thể truy cập cơ sở dữ liệu không thuộc về tôi và tôi không thể truy cập vào tiền xử lý C b) Hai câu trả lời kia không hoạt động. c) Dường như giải pháp đơn giản nhất

Đây là tập lệnh cho những người có thể thấy nó hữu ích. Tôi đang sử dụng nó để xác định các cột bảng độ rộng và sau đó sử dụng những giá trị tương tự trong các thủ tục được lưu trữ. Điều này là do độ rộng của cột chưa được quyết định hoàn toàn cho sản xuất.

Tôi cũng đã xây dựng trong đó bạn có thể xác định các chuỗi kéo dài trên một vài dòng. Điều này có lợi thế là tôi có thể tuân theo chiều rộng 80 cột (do đó in ấn có thể đọc được).

Đây là kịch bản

<?php 

if (1==count($argv)) 
{ 
?> 
Processing #defines from stdin and send to SQL server: 

This script will remove 
    1. #define <name> <integer> 
    2. #define <name> '<string>' 
    3. #define <name> '<string>' \ 
        '<continuation of string>' 

and replace the occurances of name with the #define value as specified 

<name> is upper case alpha numberics or underscores, not starting with a 
digit. 

The arguments of this script is passed to the mysql executable. 
<?php 
    exit(1); 
} 
function replace(&$newValues, $a, $b, $c) 
{ 
    return $a . (array_key_exists($b, $newValues) ? $newValues[$b] : $b) . $c; 
} 

// The patterns to be used 
$numberPattern='/^#define[ \t]+([A-Z_][A-Z0-9_]*)[ \t]+(0|([1-9][0-9]*))'. 
       '[ \t]*[\r\n]+$/'; 
$stringPattern= '/^#define[ \t]+([A-Z_][A-Z0-9_]*)[ \t]+\''. 
       '((\\\'|[^\'\r\n])*)\'[ \t]*(\\\\{0,1})[\n\r]+$/'; 
$continuationPattern='/^[ \t]*\'((\\\'|[^\'\r\n])*)\'[ \t]*'. 
        '(\\\\{0,1})[\n\r]+$/'; 

// String to be evaluated to replace define values with a new value 
$evalStr='replace($newValues, \'\1\', \'\2\', \'\3\');'; 

array_splice($argv, 0, 1); 
// Open up the process 
$mysql=popen("mysql ".implode(' ', $argv), 'w'); 

$newValues=array(); // Stores the defines new values 

// Variables to control the replacement process 
$define=false; 
$continuation=false; 
$name=''; 
$value=''; 

while ($line=fgets(STDIN)) 
{ 
    $matches=array(); 

    // #define numbers 
    if (!$define && 
     1 == preg_match($numberPattern, $line, $matches)) 
    { 
     $define = true; 
     $continuation = false; 
     $name = $matches[1]; 
     $value = $matches[2]; 
    } 

    // #define strings 
    if (!$define && 
     1 == preg_match($stringPattern, 
         $line, $matches)) 
    { 
     $define = true; 
     $continuation = ('\\' == $matches[4]); 
     $name = $matches[1]; 
     $value = $matches[2]; 
    } 

    // For #define strings that continue over more than one line 
    if ($continuation && 
     1 == preg_match($continuationPattern, 
         $line, $matches)) 
    { 
     $value .= $matches[1]; 
     $continuation = ('\\' == $matches[3]); 
    } 

    // Have a complete #define, add to the array 
    if ($define && !$continuation) 
    { 
     $define = $continuation = false; 
     $newValues[$name]=$value; 
    } 
    elseif (!$define) 
    { 
     // Do any replacements 
     $line = preg_replace('/(^| |\()([A-Z_][A-Z0-9_]*)(\)| |$)/e', 
          $evalStr, $line); 
     echo $line; // In case we need to have pure SQL. 
     // Send it to be processed. 
     fwrite($mysql, $line) or die("MySql has failed!"); 
    } 
} 
pclose($mysql); 
?>