0
CREATE TABLE Storage
(
    ID INT IDENTITY(1,1) PRIMARY KEY,
    data XML NOT NULL
)

GO

INSERT INTO Storage(data) 
VALUES('
<footballteams>   
    <team manager="Benitez">     
        <name>Liverpool</name>     
        <ground>Anfield</ground>   
    </team>   
    <team manager="Mourinho">     
        <name>Chelsea</name>     
        <ground>Stamford Bridge</ground>   
    </team>   
    <team manager="Wenger">     
    <name>Arsenal</name>     
        <ground>Highbury</ground>   
    </team> 
</footballteams>'); 
----------------------------------------
GO

CREATE VIEW FootballView WITH SCHEMABINDING AS 
(    
    SELECT            
        TeamName = Team.TeamNode.value('(name)[1]', 'varchar(100)'),              
        Manager = Team.TeamNode.value('(@manager)', 'varchar(100)'),              
        Ground = Team.TeamNode.value('(ground)[1]', 'varchar(100)')    
    FROM         
        dbo.Storage S          
        CROSS APPLY DATA.nodes('/footballteams') AS Teams(TeamsNode)
        CROSS APPLY data.nodes('/footballteams/team') AS Team(TeamNode)
)
GO
CREATE UNIQUE CLUSTERED INDEX TeamNameInd ON FootballView(TeamName)

-

Error Message: Cannot create index on view "CF.dbo.FootballView" because it contains an APPLY. Consider not indexing the view, or removing APPLY.

CROSS APPLY が使用されているため、このビューのインデックスを作成できないことは確かです。誰でもこれに対する回避策を提案できますか? 大量の XML データを処理する場合、インデックスが作成されていないこのようなビューの操作は非常に遅くなります。

編集:

XML 自体にインデックスを付ける方法はありますか?

4

1 に答える 1

0

XMLデータをSQLリレーショナルテーブルに解析し、単純なトリガーを使用してテーブルの同期を維持することで、この問題を解決できます(おそらくパフォーマンスが向上します)。次のスクリプトは、それを実行する方法のサンプルであり、あなたのケースに役立つことを願っています。

CREATE TABLE Storage (
  id INT IDENTITY(1,1) PRIMARY KEY,
  data XML NOT NULL
);

CREATE TABLE FootballTable (
  id INT,
  teamName varchar(100),
  manager varchar(100),
  ground varchar(100)
);
GO

CREATE TRIGGER TG_INS_Storage ON Storage
FOR INSERT, UPDATE, DELETE AS
BEGIN
  DELETE FootballTable WHERE id IN (SELECT dlt.id FROM deleted dlt);

  INSERT FootballTable (id, teamName, manager, ground)
  SELECT ins.id,
    TeamName = Team.TeamNode.value('(name)[1]', 'varchar(100)'),
    Manager  = Team.TeamNode.value('(@manager)', 'varchar(100)'),
    Ground   = Team.TeamNode.value('(ground)[1]', 'varchar(100)')
  FROM inserted ins
  CROSS APPLY ins.data.nodes('/footballteams/team') AS Team(TeamNode);
END

INSERT INTO Storage(data) 
VALUES('
<footballteams>
  <team manager="Benitez"><name>Liverpool</name><ground>Anfield</ground></team>   
  <team manager="Mourinho"><name>Chelsea</name><ground>Stamford Bridge</ground></team>   
  <team manager="Wenger"><name>Arsenal</name><ground>Highbury</ground></team> 
</footballteams>');
GO
SELECT * FROM FootballTable;
于 2012-06-29T16:09:04.527 に答える