我有这样的表:
CREATE TABLE [dbo].[tbl](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Year] [int] NOT NULL,
[Month] [int] NOT NULL,
[Fields] [xml] NOT NULL,
[NameFromXML] [nvarchar](1000) NULL
) ON [PRIMARY]
在Fields
列中我像这样存储XML:
<Employees>
<Person>
<ID>0</ID>
<Name>Ligha</Name>
<LName>Agha</LName>
</Person>
</Employees>
好的。我希望Name
元素的持久值为NameFromXML
。我写这个函数:
CREATE FUNCTION dbo.GetName
(
@xml XML
)
RETURNS NVARCHAR(100)
WITH RETURNS NULL ON NULL INPUT
AS
BEGIN
RETURN @xml.value('/Employees[1]/Person[1]/Name[1]', 'nvarchar(100)')
END
GO
但是当我编写此代码以添加默认值时:
ALTER TABLE tbl_Test_XML_Index_View ADD CONSTRAINT df_f DEFAULT(dbo.GetName(Fields))
FOR namefromXML
我收到了这个错误:
名称&#34;字段&#34;在这种情况下是不允许的。有效表达式是常量,常量表达式和(在某些上下文中)变量。不允许使用列名。
我如何解决这个问题?
答案 0 :(得分:1)
您似乎正在尝试为每一行存储冗余数据。如果XML中的某个名称发生了变化,会发生什么?您如何注意更新NameFromXML列?通过使用触发器?我可以给你建议,只使用常规列存储你需要的数据。编写插入/更新存储过程将把XML作为参数,并将数据从中插入到适当的列中。
答案 1 :(得分:1)
为什么不将它作为计算列,始终是正确的,并且不再需要维护工作:
CREATE FUNCTION dbo.GetName
(
@xml XML
)
RETURNS NVARCHAR(100)
WITH RETURNS NULL ON NULL INPUT
, SCHEMABINDING
AS
BEGIN
RETURN @xml.value('/Employees[1]/Person[1]/Name[1]', 'nvarchar(100)')
END
GO
CREATE TABLE [dbo].[tbl](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Year] [int] NOT NULL,
[Month] [int] NOT NULL,
[Fields] [xml] NOT NULL,
[NameFromXML] AS dbo.GetName(Fields) persisted
) ON [PRIMARY]
insert into dbo.tbl (Year,Month,Fields)
select 1,1,'<Employees>
<Person>
<ID>0</ID>
<Name>Ligha</Name>
<LName>Agha</LName>
</Person>
</Employees>'
select * from dbo.tbl
我必须在函数中添加SCHEMABINDING
,以便将其视为 deterministic 。反过来,这允许我将计算列标记为persisted
,这意味着如果需要,它可以被索引。