2012-02-11 20 views
6

我有一個腳本,我用它來構建表和存儲過程。例如,我有一個類型爲varchar的列。 varchar需要大小參數,該大小也用作存儲過程中的參數以及這些過程中的參數。SQL腳本 - 是否存在#define的等價物?

是否有可能與它的大小有相同的#define,所以我可以很容易地調整大小而不必更改整個腳本的大小?

我正在使用MySql工作臺。

編輯

我試圖SETDECLARE

我有一個腳本 - 這是(有刪節)

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

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

我所試圖實現的是替代值25具有常量的腳本 - 類似於創建表並存儲在腳本頂部的#define程序,所以我能夠輕鬆地將25改爲另一個號碼。

有人找到了解決這個問題的辦法嗎?

+0

申報的嗎? http://dev.mysql.com/doc/refman/5.0/en/declare-local-variable.html – 2012-02-11 08:57:39

+0

我寫了一些軟件來做這樣的事情 - 它是免費的,它在這裏http:// mysql-pre- processor.batcave.net/。只需將一些東西放入您選擇的慈善機構的桶中 – 2013-05-05 21:10:04

回答

18

的C預處理器(CPP)是歷史上與C(因此而得名)相關聯的,但它確實是一個通用的文本處理器可使用的(或虐待)爲別的東西。

請考慮這個名爲location.src的文件(稍後會詳細介紹)。

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

和文件debug.src,其中包括:

#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 

當編譯:

cpp -E location.src -o location.sql 

你得到你正在尋找的代碼,與CPP擴大的#define值。

當編譯:

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

你得到同樣的,再加上斷言宏(貼作爲獎金,顯示什麼可以來完成)。

假設與HAVE_DEBUG在測試環境中部署了一個版本(5.5或更高版本,因爲信號時),結果是這樣的:

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 ? 

注意怎樣的文件名,行號,條件點在源代碼中位置爲location.src的位置,這是assert被引發的地方,再次感謝C預處理器。

現在,有關 「的.src」 文件擴展名:

  • 你可以使用任何東西。
  • 擁有不同的文件擴展名有助於makefile等,並防止混淆。

編輯:最初發布爲.xql,爲清晰起見,重命名爲.src。這裏沒有涉及到xml查詢。

與任何工具一樣,使用cpp可以帶來好的結果,而以便攜方式維護LOCATION_LEN的用例看起來非常合理。 它也可能導致不好的事情,有太多的#include,嵌套的#ifdef地獄,宏等,最後混淆代碼,所以你的里程可能會有所不同。

有了這個答案,你會得到整個事情(#define#include#ifdef__FILE____LINE__#C,命令行選項來建立),所以我希望它應該涵蓋一切。

+4

巧妙。我從來沒有想過在SQL文件上使用預處理器。 – njr101 2012-02-14 15:55:40

+0

我希望有一個不需要使用預處理器的解決方案。但我會探索這個選項。 – 2012-02-16 09:16:00

1

你試過SET嗎?

這裏有一個例子:

SET @var_name = expr 

更多的例子在這裏: http://dev.mysql.com/doc/refman/5.0/en/user-variables.html

+0

我已經嘗試過申報和設置。只是想在腳本的頂部放置各種字段的大小。腳本的其餘部分根據這些值創建表/視圖/存儲過程/函數。只是爲了更容易地重建具有不同字段大小的數據庫。 – 2012-02-11 09:07:55

+0

啊...也許你想閱讀這個http://stackoverflow.com/questions/1009954/mysql-variable-vs-variable-whats-the-difference,你可以用'SET'分配一個全局變量http:/ /dev.mysql.com/doc/refman/5.1/en/set-option.html – 2012-02-11 09:14:39

0

對於那些有興趣:

我最後寫一個PHP腳本,因爲:

一)可以訪問數據庫中的機器不屬於我,我無法訪問C 預處理 b)其他兩個答案不起作用。 c)看起來最簡單的解決方案

這是誰可能會發現它有用的腳本。我使用它來定義表格列 寬度,然後在存儲過程中使用這些相同的值。這是由於 列的寬度尚未完全決定生產。

我也建立了你可以定義持續幾行的字符串。這有一個好處,我可以服從80列寬(因此打印看起來可讀)。

這裏是腳本

<?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); 
?> 
相關問題