我的存储过程执行SELECT ... INTO var
产生 NULL,但如果我SELECT
自己重复相同的操作,我会得到一个值。
这是架构的相关部分
CREATE TABLE UrlAuthority
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(255) NOT NULL COMMENT 'includes TLD suffix'
,UNIQUE(name)
)
ENGINE = INNODB DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE TABLE UrlFqdn
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY
,authority BIGINT NOT NULL COMMENT 'references example.com'
,name VARCHAR(255) NOT NULL COMMENT 'host.example.com'
,FOREIGN KEY (authority) REFERENCES UrlAuthority (id)
,UNIQUE (authority, name)
)
ENGINE = INNODB DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE TABLE Url
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY
,fqdn BIGINT NOT NULL
,path VARCHAR(255) NOT NULL
,FOREIGN KEY (fqdn) REFERENCES UrlFqdn (id)
,UNIQUE (fqdn, path)
)
ENGINE = INNODB DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Run Code Online (Sandbox Code Playgroud)
这是程序
CREATE PROCEDURE UrlToId (url TEXT)
BEGIN
DECLARE host TEXT;
DECLARE authority TEXT;
DECLARE tld TEXT;
DECLARE pathtext TEXT;
DECLARE authority_tld TEXT;
DECLARE fqdn TEXT;
DECLARE authority_id BIGINT;
DECLARE fqdn_id BIGINT;
DECLARE url_id BIGINT;
DECLARE err TEXT;
CALL UnpackURL (url, host, authority, tld, pathtext);
SELECT JoinHostNames(authority, tld) INTO authority_tld;
SELECT JoinHostNames(host, authority_tld) INTO fqdn;
INSERT IGNORE INTO UrlAuthority (name) VALUES (authority_tld);
SELECT id
INTO authority_id
FROM UrlAuthority
WHERE name=authority_tld;
-- LOG ('UrlAuthority', authority_tld, authority_id)
INSERT IGNORE INTO UrlFqdn (authority, name)
VALUES (authority_id, fqdn);
SELECT id
INTO fqdn_id
FROM UrlFqdn
WHERE authority=authority_id AND name=fqdn;
-- LOG ('UrlFqdn', fqdn, fqdn_id)
INSERT IGNORE INTO Url (fqdn, path) VALUES (fqdn_id, pathtext);
-- LOG ('Url', fqdn_id, pathtext)
SELECT id FROM Url WHERE fqdn=fqdn_id AND path=pathtext;
END
|
Run Code Online (Sandbox Code Playgroud)
这些LOG
行有点元编程,它们将字符串插入到调试表中。
如果我跑
call UrlToId('http://mail4.z.uk/foo/bar');
Run Code Online (Sandbox Code Playgroud)
我收到这些调试消息
UrlAuthority authority_tld=z.uk authority_id=1
UrlFqdn fqdn=mail4.z.uk fqdn_id=NULL
Url fqdn_id=NULL pathtext=/foo/bar
Run Code Online (Sandbox Code Playgroud)
显然,问题是,fqdn_id=NULL
但是,如果我手动重复执行SELECT id INFO fqdn_id
并替换跟踪中指示的变量值的查询:
SELECT id
-- INTO fqdn_id
FROM UrlFqdn
WHERE authority=1 /* authority_id */ AND name='mail4.z.uk' /* fqdn */;
Run Code Online (Sandbox Code Playgroud)
这1
将按预期进行选择。
在select
得到数据,为什么是变数NULL
后来呢?
有一段时间,这个问题让我望而却步。我不喜欢SELECT ... INTO
,所以我真的想把你的麻烦归咎于它,但没有。
问题来了。
SELECT id
INTO fqdn_id
FROM UrlFqdn
WHERE authority=authority_id AND name=fqdn;
Run Code Online (Sandbox Code Playgroud)
MySQL如何解释这个?
SELECT id
INTO fqdn_id
FROM UrlFqdn
WHERE 'mail4' = 1 AND name = 'mail4.z.uk';
/* Impossible WHERE */
/* see DECLARE authority TEXT; */
Run Code Online (Sandbox Code Playgroud)
“局部变量不应与表列同名。如果 SQL 语句(例如
SELECT ... INTO
语句)包含对列的引用和具有相同名称的声明的局部变量,则 MySQL 当前将引用解释为变量的名称。”— http://dev.mysql.com/doc/refman/5.7/en/local-variable-scope.html
对变量和列名使用相同的标识符会使调试变得一团糟,不管怎样。
归档时间: |
|
查看次数: |
5465 次 |
最近记录: |