T SQL游标返回空表

时间:2018-12-12 16:55:05

标签: sql-server tsql ssms

我正在T-SQL中构建一个游标,该游标将遍历每个数据库并设置变量,然后将这些变量放入表中。查询成功完成,但是#SaaS表为空。打印SQL表示根据变量分配中的选择使用了正确的数据库。由于我根据变量使用不同的数据库,因此游标确实从#dbNames表中提取了两列。当我查看#dbNames表时,由于查询跨越多个实例SQL Server,因此列中确实包含空值,因此#dbNames表看起来像这样:

ServerName | dbName         | dbName2
-------------------------------------
sql.inst1  | wfa00Reporting | null
sql.inst1  | null           | wfa00System
sql.inst1  | wfa01Reporting | null
sql.inst1  | null           | wfa01System
sql.inst2  | wfa02Reporting | null
sql.inst2  | null           | wfa02System

我不确定我在这里缺少什么,因为没有错误。为什么#SaaS表在查询完成后为空?

SQL:

/* start */

begin try
DROP TABLE #SaaS
end try
begin catch
end catch
begin try
DROP TABLE #dbNames
end try
begin catch
end catch
DECLARE
         @prefix nvarchar(50) =  'WFA'

/**
* Create 2 temp tables for processing
*/
CREATE TABLE #dbNames (dbName NVARCHAR(255)
                        , dbName2 NVARCHAR(255))

CREATE TABLE #SaaS (dbName NVARCHAR(255)
                    , varA NVARCHAR(255)
                    , varB NVARCHAR(255))

/**
* Get the databases - all for now
*/
INSERT INTO #dbNames(dbName, dbName2)
SELECT CASE WHEN [name] LIKE '%Reporting' THEN [name] END as dbName
        , CASE WHEN [name] LIKE '%System' THEN [name] END as dbName2
FROM SYS.DATABASES 
WHERE State = 0 

/**
* A few variables for the Database list cursor
*/
DECLARE @dbName NVARCHAR(255)
      , @dbName2 NVARCHAR(255)
      , @sql NVARCHAR(MAX)

/**
* get the values, only from ACA instances
*/
DECLARE EachDatabase CURSOR FOR 
 SELECT distinct [dbName],
        [dbName2]
 FROM #dbNames

OPEN EachDatabase 
FETCH NEXT FROM EachDatabase INTO @dbName, @dbName2

WHILE @@FETCH_STATUS <> -1
BEGIN

  SET @sql = '
                    DECLARE @varA AS nvarchar(255), @varB AS NVARCHAR(255)

                    SET @varB = (
                                        SELECT customerName
                                        FROM ' + @dbName2 + '.User.SystemSettings
                                        )

                    SET @varA = (
                                    select top 1 varA
                                    from
                                    ' + @dbName + '.eUser.tablecol
                                    WHERE varA >= 1/1/2018
                                    )

                    --REPORT STATUS

                    insert into #SaaS ( DBName
                                        , varA
                                        , varB
                                        )
                    select ''' + REPLACE(@dbName,'Reporting','') + '''
                            , @varA
                            , @varB
            '

  exec(@sql)

  FETCH NEXT FROM EachDatabase INTO @dbName, @dbName2
END

CLOSE EachDatabase
DEALLOCATE EachDatabase
-----------------------------------------End Table for SaaS

SELECT *
from #SaaS
order by dbName

/* end */

2 个答案:

答案 0 :(得分:0)

/* start */

begin try
DROP TABLE #SaaS
end try
begin catch
end catch
begin try
DROP TABLE #dbNames
end try
begin catch
end catch
DECLARE
         @prefix nvarchar(50) =  'WFA'

/**
* Create 2 temp tables for processing
*/
CREATE TABLE #dbNames (dbName NVARCHAR(255)
                        , dbName2 NVARCHAR(255) NULL)

CREATE TABLE #SaaS (dbName NVARCHAR(255)
                    , varA NVARCHAR(255)
                    , varB NVARCHAR(255))

/**
* Get the databases - all for now
*/
INSERT INTO #dbNames(dbName)
SELECT [name]
FROM SYS.DATABASES 
WHERE State = 0 
AND name LIKE '%Reporting'

UPDATE #dbNames
SET dbName2 = REPLACE(dbName, 'Reporting', 'System')
/**
* A few variables for the Database list cursor
*/
DECLARE @dbName NVARCHAR(255)
      , @dbName2 NVARCHAR(255)
      , @sql NVARCHAR(MAX)

/**
* get the values, only from ACA instances
*/
DECLARE EachDatabase CURSOR FOR 
 SELECT distinct [dbName],
        [dbName2]
 FROM #dbNames

OPEN EachDatabase 
FETCH NEXT FROM EachDatabase INTO @dbName, @dbName2

WHILE @@FETCH_STATUS <> -1
BEGIN

  SET @sql = '
                    DECLARE @varA AS nvarchar(255), @varB AS NVARCHAR(255)

                    SET @varB = (
                                        SELECT customerName
                                        FROM ' + @dbName2 + '.User.SystemSettings
                                        )

                    SET @varA = (
                                    select top 1 varA
                                    from
                                    ' + @dbName + '.eUser.tablecol
                                    WHERE varA >= 1/1/2018
                                    )

                    --REPORT STATUS

                    insert into #SaaS ( DBName
                                        , varA
                                        , varB
                                        )
                    select ''' + REPLACE(@dbName,'Reporting','') + '''
                            , @varA
                            , @varB
            '

  exec(@sql)

  FETCH NEXT FROM EachDatabase INTO @dbName, @dbName2
END

CLOSE EachDatabase
DEALLOCATE EachDatabase
-----------------------------------------End Table for SaaS

SELECT *
from #SaaS
order by dbName

/* end */

答案 1 :(得分:0)

@brad指出的问题是临时表#dbNames包含NULL值。这是更新的SQL,它使我不仅可以接收所需的输出,还可以创建一个临时表,而没有来自不同SQL实例上不同数据库的null值传递给游标。可能有一种“更好”的方式,但这解决了我的问题。

SQL:

 public T GetSimpleModelFromMultiNode<T> (FicheArticleViewModel model, string alias) where T: new()
        {
            var listeItems = CurrentPage.GetPropertyValue<IEnumerable<IPublishedContent>>(alias);

            var result = new T();

            //if (typeof(T) == typeof(SimpleGenericModel))
            //{
            //    result = new SimpleGenericModel();
            //}
            //else if (typeof(T) == typeof(RegionViewModel))
            //{
            //    result = new RegionViewModel();

            //}
            //else if (typeof(T) == typeof(SecteurDActiviteViewModel))
            //{
            //    result = new SecteurDActiviteViewModel();
            //}

            if (!CurrentPage.HasValue(alias)) return result;

            foreach (var item in listeItems)
            {
                result.Id = item.Id.ToString();
                result.Nom = item.Name;
            }

            return result;
        }