本節包含一些範例,說明在各種情況下使用 JavaScript 程式的不同方面。
以下範例示範如何將 JavaScript 儲存函數與資料表欄值搭配使用。首先,我們定義一個儲存函數 gcd()
,它會找出兩個整數的最大公因數,如下所示
mysql> CREATE FUNCTION gcd(a INT, b INT)
-> RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS
-> $mle$
$> let x = Math.abs(a)
$> let y = Math.abs(b)
$> while(y) {
$> var t = y
$> y = x % y
$> x = t
$> }
$> return x
$> $mle$
-> ;
Query OK, 0 rows affected (0.01 sec)
我們可以像這樣測試儲存函數
mysql> SELECT gcd(75, 220), gcd(75, 225);
+--------------+--------------+
| gcd(75, 220) | gcd(75, 225) |
+--------------+--------------+
| 5 | 75 |
+--------------+--------------+
1 row in set (0.00 sec)
接下來,我們建立一個具有兩個整數欄位的資料表 t1
,並使用一些資料列填入它,如下所示
mysql> CREATE TABLE t1 (c1 INT, c2 INT);
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO t1 VALUES ROW(12,70), ROW(17,3), ROW(81,9);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> TABLE t1;
+------+------+
| c1 | c2 |
+------+------+
| 12 | 70 |
| 17 | 3 |
| 81 | 9 |
+------+------+
3 rows in set (0.00 sec)
現在,我們可以從 t1
中選取,並使用 gcd()
函數,其中欄位值在函數呼叫中用作引數值,如下所示
mysql> SELECT c1, c2, gcd(c1, c2) AS G
-> FROM t1
-> WHERE gcd(c1, c2) > 1
-> ORDER BY gcd(c1, c2);
+----+----+---+
| c1 | c2 | G |
+----+----+---+
| 12 | 70 | 2 |
| 81 | 9 | 9 |
+----+----+---+
8 rows in set (0.01 sec)
當引數值不是指定的類型時,如果可以,會強制轉換為正確的類型,如下所示
mysql> SELECT gcd(500.3, 600), gcd(500.5, 600);
+-----------------+-----------------+
| gcd(500.3, 600) | gcd(500.5, 600) |
+-----------------+-----------------+
| 100 | 3 |
+-----------------+-----------------+
1 row in set (0.01 sec)
使用 Math.round()
完成浮點數值到整數的捨入;在本例中,500.3 會向下捨入為 500,而 500.5 會向上捨入為 501。
接下來,我們使用 CREATE PROCEDURE
陳述式建立一個簡單的 JavaScript 儲存程序,其中包含一個 OUT
參數,以將目前日期和時間以人類可讀的格式傳遞至使用者變數。由於我們不確定此表示法的長度,因此我們對參數的類型使用 VARCHAR(25)。
mysql> CREATE PROCEDURE d1 (OUT res VARCHAR(25))
-> LANGUAGE JAVASCRIPT
-> AS
-> $$
$> let d = new Date().toString()
$> res = d
$> $$
-> ;
Query OK, 0 rows affected (0.01 sec)
我們現在可以測試儲存程序,首先驗證使用者變數 @today 尚未設定為任何值,如下所示
mysql> SELECT @today;
+----------------------+
| @today |
+----------------------+
| NULL |
+----------------------+
1 row in set (0.01 sec)
mysql> CALL d1(@today);
ERROR 1406 (22001): Data too long for column 'res' at row 1
此程序在語法上有效,但是 INOUT
參數 (res
) 的資料類型不允許足夠的字元數;儲存程式會拒絕它,而不是截斷值。由於無法就地變更程序程式碼,因此我們必須捨棄程序並重新建立它;這次我們嘗試將為 INOUT
參數指定的長度加倍
mysql> DROP PROCEDURE d1;
Query OK, 0 rows affected (0.02 sec)
mysql> CREATE PROCEDURE d1 (OUT res VARCHAR(50))
-> LANGUAGE JAVASCRIPT
-> AS
-> $$
$> let d = new Date().toString()
$> res = d
$> $$
-> ;
Query OK, 0 rows affected (0.01 sec)
現在我們可以重複測試,如下所示
mysql> SELECT @today;
+----------------------+
| @today |
+----------------------+
| NULL |
+----------------------+
1 row in set (0.01 sec)
在使用 CALL
叫用更新的程序之前,@today
的值仍未設定,因為 d1()
的原始版本未成功執行。更新的版本執行成功,並且我們稍後看到,這次使用者變數的值已如預期般設定
mysql> CALL d1(@today);
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @today;
+-----------------------------------------+
| @today |
+-----------------------------------------+
| Mon Oct 30 2023 20:47:29 GMT+0000 (GMT) |
+-----------------------------------------+
1 row in set (0.00 sec)
您從執行此範例獲得的值很可能與此處顯示的值有所不同,因為日期的確切表示法取決於您的系統地區設定,以及其他可能設定。如需更多資訊,請參閱 JavaScript Date
物件的文件。
下一個範例示範如何在觸發程序中使用 JavaScript 儲存函數。
首先,我們建立一個包含三個整數欄位的資料表 t2
,如下所示
mysql> CREATE TABLE t2 (c1 INT, c2 INT, c3 INT);
Query OK, 0 rows affected (0.04 sec)
現在,我們可以在這個資料表上建立一個觸發程序。這必須使用以一般方式使用 SQL 撰寫的 CREATE TRIGGER
陳述式來完成(請參閱第 27.4 節,「使用觸發程序」),但它可以利用以 JavaScript 撰寫的儲存常式,例如本節稍早所示的 js_pow()
函數。
mysql> delimiter //
mysql> CREATE TRIGGER jst BEFORE INSERT ON t2
-> FOR EACH ROW
-> BEGIN
-> SET NEW.c2 = js_pow(NEW.c1, 2);
-> SET NEW.c3 = js_pow(NEW.c1, 3);
-> END;
-> //
Query OK, 0 rows affected (0.02 sec)
mysql> delimiter ;
mysql>
此觸發程序會在將資料列插入 t2
時執行,它會取用插入第一個欄位的值,並將此值的平方插入第二個欄位,並將其立方插入第三個欄位。我們藉由將一些資料列插入資料表來測試觸發程序;由於唯一未捨棄的值是我們為欄位 c1
提供的值,因此我們可以針對其餘兩個欄位簡單地使用 NULL
,如下所示
mysql> INSERT INTO t2
-> VALUES
-> ROW(1, NULL, NULL),
-> ROW(2.49, NULL, NULL),
-> ROW(-3, NULL, NULL),
-> ROW(4.725, NULL, NULL);
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
由於觸發程序叫用的函數是以 JavaScript 撰寫,因此會套用 JavaScript 捨入規則,因此 2.49 會向下捨入為 2,而 4.75 會向上捨入為 5。當我們使用 TABLE
陳述式檢查結果時,可以看到事實確實如此
mysql> TABLE t2;
+------+------+------+
| c1 | c2 | c3 |
+------+------+------+
| 1 | 1 | 1 |
| 2 | 4 | 8 |
| -3 | 9 | -27 |
| 5 | 25 | 125 |
+------+------+------+
4 rows in set (0.00 sec)