2012-02-11 15 views
6

私は、テーブルとストアドプロシージャの両方を構築するために使用するスクリプトを用意しています。たとえば、タイプがvarcharのカラムがあります。 varcharにはsizeパラメータが必要です。そのサイズは、ストアドプロシージャやそのプロシージャ内のパラメータとしても使用されます。SQLスクリプト - #defineに相当するものはありますか?

そのサイズは#defineであることが可能ですので、スクリプト全体を変更しなくても簡単にサイズを調整できますか?

私はMySqlワークベンチを使用しています。私は、スクリプトを持っているSETDECLARE

を試してみました

EDIT

- これは、(簡略)されて、私が達成しようとしています何

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 –

+0

私はこのようなことをするためにいくつかのSWを書いた - それは無料でここにhttp:// mysql-pre- processor.batcave.net/。あなたの好きな慈善団体のバケツにいくつか入れてください –

答えて

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 

をあなたが同じを取得し、プラスASSERTマクロは(何ができるかを示すために、ボーナスとして掲載)。

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 ? 

注意をどのようにファイル名、行番号、および条件ポイント:(SIGNALを使用しているので、5.5以降で)結果は次のようになり、テスト環境で展開HAVE_DEBUGとビルドを想定すると

アサートが発生したlocation.srcのソースコードの場所で、Cプリプロセッサに再度感謝します。今

、 ".SRC" ファイルの拡張子について:

  • あなたが何かを使用することができます。
  • ファイルの拡張子が異なると、makefileなどに役立ち、混乱を避けることができます。

EDIT:もともと.xqlとして公開されていますが、わかりやすくするため.srcに名前が変更されました。ここでxmlクエリに関連するものはありません。

どんなツールでも、cppを使うと良いものが得られ、LOCATION_LENを移植性のある方法で維持するためのユースケースは非常に合理的です。 #include、#ifdef hell、マクロなどが多すぎると、コードが難読化されることもありますので、マイレージが異なる場合があります。この答えを

は、あなたが(#define#include#ifdef__FILE____LINE__#C、コマンドラインオプション構築する)全体を取得するので、私はそれはそれをすべてをカバーする必要があります願っています。

興味があるものについては
+4

独創的です。私はSQLファイルにプリプロセッサを使用することは考えていませんでした。 – njr101

+0

私は、プリプロセッサの使用を必要としないソリューションを期待していました。しかし、私はこのオプションを探求します。 –

1

SETを試しましたか?ここ

は一例です。ここ

SET @var_name = expr 

より多くの例:ユーザー定義のデータ型を探しているよう http://dev.mysql.com/doc/refman/5.0/en/user-variables.html

+0

私は宣言と設定の両方を試みました。スクリプトの上部にさまざまなフィールドのサイズを入れたいだけです。残りのスクリプトは、これらの値に基づいてテーブル/ビュー/ストアドプロシージャ/ファンクションを作成します。さまざまなフィールドの異なるサイズのデータ​​ベースを簡単に再構築できるようにするためです。 –

+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 –

1

ですね。残念ながら、私たちにとっては、すべてのmySQLは、SQL ServerやOracleなどのユーザー定義データ型をまだサポートしていません。ここで

がサポートされているデータ型のリストです:( http://dev.mysql.com/doc/refman/5.0/en/data-types.html

0

:a)のデータベースにアクセスすることができ、マシンは私に属していないと私はC プリプロセッサ にアクセスすることはできません

:ので、私はPHPスクリプトを書くことになった

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); 
?> 
関連する問題