将视图和表值函数用作match子句中的节点或边表

时间:2017-08-16 08:45:03

标签: graph graph-databases sql-server-2017 sql-server-2017-graph

我喜欢在Table Valued functions条款中使用MATCH,方法与Node tables相同。有没有办法实现这个目标?

需要表值函数

将表值函数或视图用作Node tables可以有多种用例。例如我的如下 我有Node个包含NVarChar(max)个字段的表,我想搜索文字文本。我只需要平等搜索而不需要full text searching,所以我选择在文本字段的hash value上使用索引。正如Remus RusanuanswerSQL 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]会根据$node_id的建议,使用别名NodeId返回https://stackoverflow.com/a/45565410/814206。但是,真正的Node tables包含两个内部列,我不知道如何导出。

所需查询

我想查询与此类似的数据库:

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

但是,这会导致错误 1

  

Msg 13901,Level 16,State 2,Line ...
  MATCH子句中的标识符't'不是node table或节点表的别名。

我有办法做到这一点吗?

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

1 这为Difference between View and table in sql的视图和表格提供了非常具体的区别;仅在中出现且仅在使用SQL Graph时出现。

3 个答案:

答案 0 :(得分:0)

解决方法

通过JOIN子句或FROM with <table_or_view_name>WHERE子句恢复传统的关系联接。在match关于更多关系的查询中,后者的优势是可以MATCH FROM <table_or_view_name> FROM <table_source> JOIN <table_source>而不是enter image description here

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;

答案 1 :(得分:0)

解决方法

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

这会影响效果吗?

答案 2 :(得分:0)

解决方法

不要使用表值函数,而是在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