SQL 脚本 - 是否存在与 #define 等效的内容?

发布于 2025-01-05 02:56:30 字数 612 浏览 0 评论 0原文

我有一个脚本,用于构造表和存储过程。例如,我有一个 varchar 类型的列。 varchar 需要一个大小参数,该大小我也在存储过程和这些过程中用作参数。

是否可以使用 #define 的大小来等效,这样我就可以轻松调整大小,而无需更改整个脚本?

我正在使用 MySql 工作台。

编辑

我已经尝试过SETDECLARE

我有一个脚本 - 这是(删节)

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

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

我想要实现的是将值 25 替换为带有常量的脚本 - 类似于创建表和存储过程的脚本顶部的#define,因此我可以轻松地将 25 更改为另一个数字。

有人找到解决这个问题的方法了吗?

I have a script that I use to construct both the tables and stored procedures. For example I have a column of type varchar. varchar requires a size parameter, that size I also use as parameters in stored procedures and within those procedures.

is it possible to have thequivalentnt of a #define for its size, so I can easily adjust the size without the necessity of having to change ithroughht the whole of the script?

I am using MySql workbench.

EDIT

I have tried SET and DECLARE

I have a script - this is (abridged)

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

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

What I am trying to achieve is replace the values 25 in the script with a constant - similar to a #define at the top of the script that creates the table and stored procedures, so I am able to easily change the 25 to another number.

Anybody has found a solution to this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

雨后咖啡店 2025-01-12 02:56:30

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 宏(作为奖励发布,以显示可以做什么)。

假设在测试环境中部署了 HAVE_DEBUG 构建(在 5.5 或更高版本中,因为使用了 SIGNAL),结果如下所示:

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 ?

注意文件名、行号和条件如何指向源代码中的位置。 src 是引发断言的地方,再次感谢 C 预处理器。

现在,关于“.src”文件扩展名:

  • 您可以使用任何内容。
  • 使用不同的文件扩展名有助于 makefile 等,并防止混淆。

编辑:最初发布为 .xql,为了清晰起见,重命名为 .src。这里没有与 xml 查询相关的内容。

与任何工具一样,使用 cpp 可以带来好处,并且以可移植方式维护 LOCATION_LEN 的用例看起来非常合理。
它还可能导致不好的事情,太多的 #include、嵌套的 #ifdef 地狱、宏等最终会混淆代码,所以你的情况可能会有所不同。

有了这个答案,你就得到了整个事情(#define#include#ifdef__FILE__,< code>__LINE__、#C、要构建的命令行选项),所以我希望它应该涵盖所有内容。

The C Pre Processor (cpp) is historically associated with C (hence the name), but it really is a generic text processor that can be used (or abused) for something else.

Consider this file, named location.src (more on that later).

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

and file debug.src, which is included:

#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

When compiled with:

cpp -E location.src -o location.sql

you get the code you are looking for, with cpp expanding #define values.

When compiled with:

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

you get the same, plus the ASSERT macro (posted as a bonus, to show what could be done).

Assuming a build with HAVE_DEBUG deployed in a testing environment (in 5.5 or later since SIGNAL is used), the result looks like this:

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 ?

Note how the file name, line number, and condition points right at the place in the source code in location.src where the assert is raised, thanks again to the C pre processor.

Now, about the ".src" file extension:

  • you can use anything.
  • Having a different file extension helps with makefiles, etc, and prevents confusion.

EDIT: Originally posted as .xql, renamed to .src for clarity. Nothing related to xml queries here.

As with any tools, using cpp can lead to good things, and the use case for maintaining LOCATION_LEN in a portable way looks very reasonable.
It can also lead to bad things, with too many #include, nested #ifdef hell, macros, etc that at the end obfuscate the code, so your mileage may vary.

With this answer, you get the whole thing (#define, #include, #ifdef, __FILE__, __LINE__, #C, command line options to build), so I hope it should cover it all.

旧情勿念 2025-01-12 02:56:30

你尝试过SET吗?

这是一个例子:

SET @var_name = expr

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

Have you tried SET?

here is an example :

SET @var_name = expr

more examples here :
http://dev.mysql.com/doc/refman/5.0/en/user-variables.html

孤凫 2025-01-12 02:56:30

听起来您正在寻找用户定义的数据类型。不幸的是,对于我们所有人来说,mySQL 尚不支持用户定义的数据类型,如 SQL Server、Oracle 等。

以下是支持的数据类型的列表:
http://dev.mysql.com/doc/refman/5.0 /en/data-types.html

It sounds like you're looking for user defined data types. Unfortunately for us all mySQL doesn't yet support user defined data types like SQL Server, Oracle, and others do.

Here's a list of supported data types:
http://dev.mysql.com/doc/refman/5.0/en/data-types.html

丶视觉 2025-01-12 02:56:30

对于那些感兴趣的人:

我最终编写了一个PHP脚本,因为:

a)可以访问数据库的机器不属于我,我无法访问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);
?>

For those that are interested:

I ended up writing a PHP script because:

a) The machine that can access the database does not belong to me and I cannot access the C
preprocessor
b) The other the two answers do not work.
c) Seemed the simplest solution

Here is the script for those who might find it useful. I am using it to define the tables column
widths and then use those same values in the stored procedures. This is due to the column
widths have not yet been fully decided for production.

I have also built in that you can define strings that last over a few lines. This has the advantage that I can obey the 80 column width (hence printing looks readable).

Here is the script

<?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);
?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文