Sql 如何将GETDATE()函数与xml exist()函数一起使用

Sql 如何将GETDATE()函数与xml exist()函数一起使用,sql,xml,Sql,Xml,我有一个场景,我必须在查询的where子句中使用XMLEXIST()函数。我必须将xml中的日期与当前日期进行比较。当我尝试使用GETDATE()函数时,我得到以下错误 XML数据类型方法“exist”的参数1必须是字符串文字 请考虑以下查询以供参考。 SELECT TRY_CONVERT(datetime,NULLIF(t.x.value('(./Expire)[1]','varchar(max)'), '')) as expiration_date FROM VW_Analy

我有一个场景,我必须在查询的where子句中使用XMLEXIST()函数。我必须将xml中的日期与当前日期进行比较。当我尝试使用GETDATE()函数时,我得到以下错误

XML数据类型方法“exist”的参数1必须是字符串文字

请考虑以下查询以供参考。

SELECT 
       TRY_CONVERT(datetime,NULLIF(t.x.value('(./Expire)[1]','varchar(max)'), '')) as expiration_date
FROM VW_Analytics_Base_Facts(nolock) BaseFact
CROSS APPLY BaseFact.Fact.nodes ('/Fact/Grant') t(x)
WHERE TYPE = '/asset/portfolio/option' 
AND BaseFact.Fact.exist('./Expire[(text()[1] cast as xs:date?) le xs:date("' + CONVERT(NVARCHAR(max),CONVERT(date,GETDATE()))+'")]')=1
提前谢谢

下面是更新的工作查询

DECLARE @tbl TABLE (XmlCol xml)
INSERT INTO @tbl VALUES 
('<option>
            <OptionName>Option 1</OptionName>
            <grant>
                    <GrantName>Grant 1</GrantName>
                            <schedules>
                                            <schedule>
                                                            <scheduleID></scheduleID>
                                                            <scheduleName></scheduleName>
                                                            <scheduleDate>1/1/2018</scheduleDate>
                                                            <scheduleAmount></scheduleAmount>
                                            </schedule>
                                            <schedule>
                                                            <scheduleID></scheduleID>
                                                            <scheduleName></scheduleName>
                                                            <scheduleDate>2/1/2018</scheduleDate>
                                                            <scheduleAmount></scheduleAmount>
                                            </schedule>
                                            <schedule>
                                                            <scheduleID></scheduleID>
                                                            <scheduleName></scheduleName>
                                                            <scheduleDate>3/1/2018</scheduleDate>
                                                            <scheduleAmount></scheduleAmount>
                                            </schedule>
                            </schedules>
            </grant>
            <grant>
                            <GrantName>Grant 2</GrantName>
                            <schedules>
                                            <schedule>
                                                            <scheduleID></scheduleID>
                                                            <scheduleName></scheduleName>
                                                            <scheduleDate>1/1/2019</scheduleDate>
                                                            <scheduleAmount></scheduleAmount>
                                            </schedule>
                                            <schedule>
                                                            <scheduleID></scheduleID>
                                                            <scheduleName></scheduleName>
                                                            <scheduleDate>2/1/2019</scheduleDate>
                                                            <scheduleAmount></scheduleAmount>
                                            </schedule>
                                            <schedule>
                                                            <scheduleID></scheduleID>
                                                            <scheduleName></scheduleName>
                                                            <scheduleDate>3/1/2019</scheduleDate>
                                                            <scheduleAmount></scheduleAmount>
                                            </schedule>
                            </schedules>
            </grant>
        </option>'
)



SELECT e.XmlCol.value('(/option/OptionName)[1]', 'varchar(100)'),
        t.x.value('../.././GrantName[1]','varchar(100)') GrantName,
       t.x.value('(./scheduleDate)[1]', 'varchar(100)') scheduleDate
FROM @tbl e
       CROSS APPLY (SELECT CONVERT(date,GETDATE())) dt(today)
    cross apply e.XmlCol.nodes ('/option/grant/schedules/schedule') t(x)
WHERE e.XmlCol.exist('./scheduleDate[(text()[1] cast as xs:date?) le sql:column("dt.today")]')=1
DECLARE@tbl表(xmlcolxml)
插入@tbl值
('
选择1
赠款1
1/1/2018
2/1/2018
3/1/2018
赠款2
1/1/2019
2/1/2019
3/1/2019
'
)
选择e.XmlCol.value(“(/option/OptionName)[1]”,“'varchar(100)”,
t、 x.value('../.././GrantName[1]','varchar(100)')GrantName,
t、 x.value(“(./scheduleDate)[1]”,“/varchar(100)”scheduleDate
来自@tbl e
交叉应用(选择转换(日期,GETDATE()))dt(今天)
交叉应用e.XmlCol.nodes('/option/grant/schedules/schedule')t(x)
其中e.XmlCol.exist('./scheduleDate[(text()[1]转换为xs:date?)le sql:column(“dt.today”)]=1
我想根据计划日期筛选记录。 此查询是视图的一部分,因此我无法声明变量。

下次请附加一个带有DDL、数据插入、您自己的代码和预期输出的独立工作示例。这将允许测试解决方案

在这种情况下,我必须猜测并发布未经测试的:

SELECT 
       TRY_CONVERT(datetime,NULLIF(t.x.value('(./Expire)[1]','varchar(max)'), '')) as expiration_date
FROM VW_Analytics_Base_Facts(nolock) BaseFact
CROSS APPLY (SELECT CONVERT(date,GETDATE())) dt(today)
CROSS APPLY BaseFact.Fact.nodes ('/Fact/Grant') t(x)
WHERE TYPE = '/asset/portfolio/option' 
AND BaseFact.Fact.exist('./Expire[(text()[1] cast as xs:date?) le sql:column("dt.today")]')=1;
此查询将使用另一个
交叉应用
,以便将信息包括在结果集中。函数
sql:column()

使现代化 您尽早应用过滤器的想法没有错。作为
.nodes()
中的谓词,这甚至更好。但是你必须依靠一个隐含的演员阵容,这是你不应该做的

表达式
(text()[1]强制转换为xs:date?
将使用系统的区域性。类似于
1/3/2018
的值可能被视为3月1日或1月3日。因此,我建议将值读取为字符串,并使用适当样式的
CONVERT

顺便说一句:我使用两次
交叉应用
.nodes()
来避免向后导航(
。/../


这将以派生表的形式返回XML的内容。使用一个简单的
,其中
来过滤这个派生表。

下面是我的工作

SELECT e.XmlCol.value('(/option/OptionName)[1]', 'varchar(100)') OptionName,
    t.x.value('../.././GrantName[1]','varchar(100)') GrantName,
   t.x.value('(./scheduleDate)[1]', 'varchar(100)') scheduleDate
FROM @tbl e
    CROSS APPLY e.XmlCol.nodes ('/option/grant/schedules/schedule') t(x)
WHERE TRY_CONVERT(datetime,NULLIF(t.x.value('(./scheduleDate)[1]','varchar(max)'), '')) BETWEEN CONVERT(date,GETDATE()) AND DATEADD(YEAR, 1, GETDATE())

您好,先生,我已对查询进行了更改。你给出的解决方案不起作用。请看一看。@RichiSharma我将在大约1小时后看一看这个。。。一个简短的问题:XML的创建是否在您的控制之下?如果是:以依赖于区域性的格式存储日期是一个非常糟糕的主意。如果使用
SET DATEFORMAT dmy,查询将不会返回相同的结果
设置日期格式mdy。使用像
13/1/2018
这样的值,它可能会在另一个系统上失败……我无法控制XML的创建。我所要做的就是创建一个视图来创建一个数据集。查询是视图的一部分。所以我不能像这样使用派生查询。我尝试尽早应用过滤器是为了最小化视图上的负载。目前,由于我正在解析XML,因此查询非常繁重。这就是为什么我想尽早筛选记录。如果这样可以的话。。。我不知道你是否检查了我更新的解决方案。它遵循相同的思想(获取所有值并使用一个简单的
WHERE
来过滤结果),但更优雅,更易于阅读,并且避免了一些性能杀手。如果你想坚持这一点,你至少应该添加
SELECT e.XmlCol.value('(/option/OptionName)[1]', 'varchar(100)') OptionName,
    t.x.value('../.././GrantName[1]','varchar(100)') GrantName,
   t.x.value('(./scheduleDate)[1]', 'varchar(100)') scheduleDate
FROM @tbl e
    CROSS APPLY e.XmlCol.nodes ('/option/grant/schedules/schedule') t(x)
WHERE TRY_CONVERT(datetime,NULLIF(t.x.value('(./scheduleDate)[1]','varchar(max)'), '')) BETWEEN CONVERT(date,GETDATE()) AND DATEADD(YEAR, 1, GETDATE())