使用TSQL对SQL Server版本进行编程比较

时间:2014-05-22 14:28:13

标签: sql sql-server tsql sql-server-2008-r2 sql-server-2012

为了说明这一点,我在我的环境中获得了少量2000,2005,2008,2008R2和2012服务器。我试图通过TSQL以编程方式识别哪些服务器足以连接到sys.dm_db_partition_stats。为了使事情变得复杂,MS正式推出了此功能,其中包括 SP2 on the 2008 R2 SP1 with 2012 ,并且非常适合将其包含在 RTM for 2014 < / strong>即可。我想要做的是确定我正在运行所述查询的当前SQL Server的版本,然后比较该版本是否等于或高于上述SQL Server版本/补丁级别。如果是这样,我将使用新的DMV,否则我将使用折旧的sys.sysindexes DMV。

只是为了警告你,这并不像查看主要产品版本那么简单。例如,如果我有一台SQL Server 2012 RTM服务器,它的级别高于SQL 2008 R2 SP2级别,但它在2012年的产品线上没有足够的级别,所以这个例程必须有一些明确内置的逻辑。

我尝试回避这一点并查询sys.all_views视图,但具有讽刺意味的是,早在2005年,sys.dm_db_partition_stats DMV就包含在SQL Server中,尽管尝试查询它会导致查询解析失败。

我可以使用&#34;糟糕的做法&#34;在TRY CATCH块中运行一些DSQL的解决方法,但坦率地说这确实是一种糟糕的方法,我宁愿以正确的方式进行。

所以,对于我的问题:如果SQL Server版本适合特定的Patchset级别或更高级别,是否有人可以共享一个可以以编程方式返回true / false的过程?

我自己也没有遇到过上述例行程序的问题,但我希望那里的人已经有了类似的东西。

谢谢,

约翰

2 个答案:

答案 0 :(得分:1)

我想到了一些关于使用PowerShell等存储SQL的各种构建版本的选项,直到我意识到我的真​​正问题是将Build版本转换为易于比较的东西。在NVARCHAR格式中,9.xxx的构建版本实际上大于12.xxx,因为它进行字母数字比较(例如9> 1)而不是数字比较(例如12> 9)。这总是以糟糕的方式扭曲我的结果,所以我最终做的是我最初提出了一个例程,将构建版本转换为4列查询结果我可以轻松地运行数字比较逻辑,对于Major ,次要,构建和修订版本。我将所有内容都放入IF EXISTS块中,然后根据需要获得我的真/假逻辑。

然后通过另一个论坛,提到了PARSENAME()函数,这是更容易采取的路径:

-- Will Wrap an IF EXISTS check around this query
SELECT 1
FROM (
    SELECT CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(128)), 4) AS INT) AS Major, 
            CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(128)), 3) AS INT) AS Minor, 
            CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(128)), 2) AS INT) AS Build, 
            CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(128)), 1) AS INT) AS Revision
) t
WHERE (t.Major >= 10 AND t.Minor >= 50 AND t.Build >= 4000)
    OR (t.Major >= 11 AND t.Build >= 3000)
    OR (t.Major >= 12)

这是我提出的原始代码,以防有人关心。一种使用表变量的方法;另一个是CTE。

唯一的缺点是,由于PIVOT功能,它在2005年以前的任何版本都不可行,而PARSENAME功能没有相同的问题。

-- NOTE: General Split Funcationality via http://sqlperformance.com/2012/07/t-sql-queries/split-strings

-- ### Table Var ### --

DECLARE @ProductVersion TABLE
(
    RowNum  INT IDENTITY(1,1),
    Val INT
)

INSERT INTO @ProductVersion (Val)
SELECT y.i.value('(./text())[1]', 'nvarchar(128)')
FROM 
( 
SELECT x = CONVERT(XML, '<i>' 
    + REPLACE(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(128)), '.', '</i><i>') 
    + '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)

-- Will Wrap an IF EXISTS check around this query
SELECT 1
FROM(
    SELECT MAX([1]) AS Major, MAX([2]) AS Minor, MAX([3]) AS Build, MAX([4]) AS Revision
    FROM @ProductVersion pv
    PIVOT (MAX(pv.Val) FOR RowNum IN ([1], [2], [3], [4])) AS PivotTable
) t
WHERE (t.Major >= 10 AND t.Minor >= 50 AND t.Build >= 4000)
    OR (t.Major >= 11 AND t.Build >= 3000)
    OR (t.Major >= 12)

GO


-- ### CTE ### --

-- RowNum workaround per http://connect.microsoft.com/SQLServer/feedback/details/383888/fully-support-position-in-xquery
WITH ProductVersion AS
(
    SELECT y.i.value('(./text())[1]', 'int') AS Val, row_number() over (partition by 0 order by nullif(0 * y.i.value('count(.)','int'), 0)) AS RowNum
    FROM 
    ( 
    SELECT x = CONVERT(XML, '<i>' 
        + REPLACE(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(128)), '.', '</i><i>') 
        + '</i>').query('.')
    ) AS a CROSS APPLY x.nodes('i') AS y(i)
)

-- Will Wrap an IF EXISTS check around this query
SELECT 1
FROM(
    SELECT MAX([1]) AS Major, MAX([2]) AS Minor, MAX([3]) AS Build, MAX([4]) AS Revision
    FROM ProductVersion pv
    PIVOT (MAX(pv.Val) FOR RowNum IN ([1], [2], [3], [4])) AS PivotTable
) t
WHERE (t.Major >= 10 AND t.Minor >= 50 AND t.Build >= 4000)
    OR (t.Major >= 11 AND t.Build >= 3000)
    OR (t.Major >= 12)
GO

答案 1 :(得分:0)

根据您对可以运行dm_db_partition_stats的版本的描述,这将告诉您1是否可以运行它,0如果您不能运行。

SELECT CASE
     WHEN @@VERSION LIKE '%7.00.623%' THEN 0
     WHEN @@VERSION LIKE '%7.00.699%' THEN 0
     WHEN @@VERSION LIKE '%7.00.842%' THEN 0
     WHEN @@VERSION LIKE '%7.00.960%' THEN 0
     WHEN @@VERSION LIKE '%7.00.0063%' THEN 0
     WHEN @@VERSION LIKE '%8.00.094%' THEN 0
     WHEN @@VERSION LIKE '%8.00.384%' THEN 0
     WHEN @@VERSION LIKE '%8.00.532%' THEN 0
     WHEN @@VERSION LIKE '%8.00.760%' THEN 0
     WHEN @@VERSION LIKE '%8.00.2039%' THEN 0
     WHEN @@VERSION LIKE '%9.00.0399.06%' THEN 0
     WHEN @@VERSION LIKE '%9.00.2047%' THEN 0
     WHEN @@VERSION LIKE '%9.00.3042%' THEN 0
     WHEN @@VERSION LIKE '%9.00.4035%' THEN 0
     WHEN @@VERSION LIKE '%9.00.5000%' THEN 0
     WHEN @@VERSION LIKE '%00.00.0600.22%' THEN 0
     WHEN @@VERSION LIKE '%00.00.2530%' THEN 0
     WHEN @@VERSION LIKE '%00.00.4000%' THEN 0
     WHEN @@VERSION LIKE '%00.00.5500%' THEN 0
     WHEN @@VERSION LIKE '%00.50.0600.0%' THEN 0
     WHEN @@VERSION LIKE '%00.50.2500' THEN 0
     WHEN @@VERSION LIKE '%00.00.2000.6%' THEN 0
     ELSE 1
 END