在匹配子句中使用视图和表值函数作为节点或边表

Posted

技术标签:

【中文标题】在匹配子句中使用视图和表值函数作为节点或边表【英文标题】:Use views and table valued functions as node or edge tables in match clauses 【发布时间】:2018-01-24 07:47:23 【问题描述】:

我喜欢在MATCH 子句中使用Table Valued functions,就像使用Node tables 一样。有没有办法做到这一点?

需要表值函数

可以有各种使用表值函数或视图作为Node tables 的用例。例如我的如下。 我有 Node 表,其中包含我想搜索文字文本的 NVarChar(max) 字段。我只需要相等搜索而不需要full text searching,所以我选择在文本字段的hash value 上使用索引。正如Remus Rusanu 在他的answer 到SQL server - worth indexing large string keys? 和https://www.brentozar.com/archive/2013/05/indexing-wide-keys-in-sql-server/ 中所建议的那样。表值函数使用CHECKSUM 索引处理;见Msg 207 Invalid column name $node_id for pseudo column in inline table valued function。

示例数据定义

CREATE TABLE [Tags](
    [tag] NVarChar(max),
    [tagHash] AS CHECKSUM([Tag]) PERSISTED NOT NULL
) as Node;

CREATE TABLE [Sites](
    [endPoint] NVarChar(max),
    [endPointHash] AS CHECKSUM([endPoint]) PERSISTED NOT NULL
) as Node;

CREATE TABLE [Links] as Edge;

CREATE INDEX [IX_TagsByName] ON [Tags]([tagHash]);

GO

CREATE FUNCTION [TagsByName](
    @tag NVarChar(max))
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT
    $node_id AS [NodeId],
    [tag],
    [tagHash]
FROM [dbo].[Tags]
WHERE [tagHash] = CHECKSUM(@tag) AND
    [tag] = @tag;

[TagsByName] 返回具有别名NodeId$node_id,正如https://***.com/a/45565410/814206 所建议的那样。然而,真正的Node tables 包含另外两个我不知道如何导出的内部列。

所需查询

我想查询类似这样的数据库:

SELECT *
FROM [TagsByName]('important') as t,
    [Sites] as s,
    [Links] as l
WHERE MATCH ([t]-([l])->[s])

但是,这会导致错误1

消息 13901,第 16 级,状态 2,线路 ...MATCH 子句中的标识符 't' 不是 node table 或节点表的别名。

我有办法吗?


PS。有一些解决方法,但它们看起来不像MATCH-query 那样优雅;特别是考虑到我的实际查询涉及匹配更多的关系和更多的字符串相等测试。我会将这些解决方法作为答案发布,并希望有人提出更好的想法。

1这给出了Difference between View and table in sql 的视图和表之间非常具体的区别;仅在 sql-server-2017 中出现,并且仅在使用 SQL Graph 时出现。

【问题讨论】:

【参考方案1】:

解决方法

不要使用表值函数,而是将其表达式包含在WHERE 子句中:

SELECT *
FROM [Tags] as t,
    [Sites] as s,
    [Links] as l
WHERE MATCH ([t]-([l])->[s]) AND
    [t].[tagHash] = CHECKSUM('important') AND
    [t].[tag] = 'important'

缺点:这很容易出错;例如忘记加入CHECKSUM

【讨论】:

【参考方案2】:

解决方法

Node 表两次添加到from 子句:一次作为表,一次作为表值函数,并通过where 子句中的$node_id 连接它们:

SELECT *
FROM [TagsByName]('important') as t1,
    [Tags] as t2,
    [Sites] as s,
    [Links] as l
WHERE MATCH ([t2]-([l])->[s]) AND
    t1.[NodeId] = t2.$node_id

这会影响性能吗?

【讨论】:

【参考方案3】:

解决方法

通过JOIN 子句或FROM with <table_or_view_name>WHERE 子句恢复到传统的关系连接。在更多关系上match 的查询中,后者的优势在于sql-server-2017-graph 可以MATCHFROM <table_or_view_name> 但不能上FROM <table_source> JOIN <table_source>

SELECT *
FROM [TagsByName]('important') as t
    [Sites] as s,
    [Links] as l
WHERE t.NodeId = l.$from_id AND
    l.$to_id = s.$node_id;

【讨论】:

以上是关于在匹配子句中使用视图和表值函数作为节点或边表的主要内容,如果未能解决你的问题,请参考以下文章

sql2005中 表值函数是啥

在 T-SQL 查询的 SELECT 子句中使用表值函数的“语法不正确”

使用带有标量函数的 where 条件与使用交叉应用和表值函数的 where 条件

EF 和表值函数性能

存储过程和表值函数有啥区别?

sql server表值函数和视图如何一起使用