背景: 某系统需要从正式系统中整理还原出一个测试系统出来,这时候数据库,ReportService等等也都通通整一份测试系统。这里主要讨论SSRS有可能会面临的问题。
第一:SSRS是有两个数据库的,两者之间一般通过固定的命名关联,那么还原数据库用新的数据库名之后,这个关联就不对了,这时候在ReportService中配置会发现它提示,未初始化报表服务器,或者数据库未能链接之类的。
第二:如果之前的报表里面,没有使用统一的一个共享数据源链接,那么这里可能面临很多的报表,需要一个一个去修改数据源。
针对第一个问题,它其实就是ReportServer的数据库里面,会有一些存储过程,然后它需要用到另外一个ReportServerTempDB的数据库,所以一般在初始化时会生成调用固定数据库的存储过程代码。例如:
以下是ReportServer的存储过程代码
另:在ReportService的配置器中产生新的数据库时,它是默认按照固定的命名规则来初始化产生数据库的。
所有,知道了问题的根源,那么我们要做的是将这个数据库中的所有存储过程里面,有涉及到旧的Temp数据库的全部换成新的Temp数据库就可以了。
当然,我们既然知道了这个问题,这里提供一份代码,修改参数执行之后可以替换存储过程中的数据库名,后面就可能正常使用了。
--批量替换存储过程中某个值,然后重新执行修改存储过程
--用于报表数据库还原之后,非自动初始化的报表数据库里面会有固定的数据库执行字符串,这时候还原之后需要替换
--注意,这只能替换掉大部分,其中可能会有些因为前面有注释等各种原因,导致替换执行失败,需手动替换
--多执行两次,后面会显示出每次剩下执行的存储过程
DECLARE @NewDBName NVARCHAR(100) = N'[SL901App_ReportServerTempDB]',@OldDBName NVARCHAR(100) = N'[ReportServer$SQL2012TempDB]'
SELECT ROW_NUMBER() OVER (ORDER BY b.name) AS id, b.name INTO #tttt FROM syscomments a,sysobjects b where a.id=b.id
--AND b.name = 'ExtendEditSessionLifetime'
DECLARE @i INT = 1, @Cnt INT = (SELECT COUNT(*) FROM #tttt)
--执行的时候去掉这个
--SET @Cnt = 1
WHILE @i <= @Cnt
BEGIN
DECLARE @procname NVARCHAR(1000)
SELECT @procname = name FROM #tttt WHERE id = @i
--SET @procname = 'AddBatchRecord'
CREATE TABLE #ProcText (
id INT IDENTITY(1,1),
Text NVARCHAR(4000)
)
INSERT INTO #ProcText
(Text )
EXEC sys.sp_helptext @objname = @procname, -- nvarchar(776)
@columnname = NULL -- sysname
--SELECT * FROM #ProcText
DECLARE @y INT = 1,@YCnt INT = (SELECT COUNT(*) FROM #ProcText)
DECLARE @Flag INT = 0 ;
WHILE @y <= @YCnt
BEGIN
IF (SELECT COUNT(*) FROM dbo.f_group_split((SELECT Text FROM #ProcText WHERE id = @y),@OldDBName)) > 1
BEGIN
SET @Flag = 1
BREAK
END
SET @y = @y + 1
END
IF @Flag = 0
BEGIN
--SELECT @procname,N'跳过'
DROP TABLE #ProcText
SET @i = @i + 1
CONTINUE
END
DECLARE @SQL NVARCHAR(MAX)
SET @SQL = N''
SET @y = 1
WHILE @y<=@YCnt
BEGIN
DECLARE @Text NVARCHAR(max) = (SELECT Text FROM #ProcText WHERE id = @y)
IF REPLACE(@Text,' ','') LIKE '%CREATEPROCEDURE%'
BEGIN
SET @Text = LTRIM(@Text)
SET @Text = SUBSTRING(@Text,8,LEN(@Text))
SET @Text = 'alter ' + @Text
END
IF REPLACE(@Text,' ','') LIKE '%CREATEPROC%'
BEGIN
SET @Text = LTRIM(@Text)
SET @Text = SUBSTRING(@Text,8,LEN(@Text))
SET @Text = 'alter ' + @Text
END
IF REPLACE(@Text,' ','') LIKE '%CREATEFUNCTION%'
BEGIN
SET @Text = LTRIM(@Text)
SET @Text = SUBSTRING(@Text,8,LEN(@Text))
SET @Text = 'alter ' + @Text
END
IF REPLACE(@Text,' ','') LIKE '%CREATEVIEW%'
BEGIN
SET @Text = LTRIM(@Text)
SET @Text = SUBSTRING(@Text,8,LEN(@Text))
SET @Text = 'alter ' + @Text
END
IF REPLACE(@Text,' ','') LIKE '%CREATETRIGGER%'
BEGIN
SET @Text = LTRIM(@Text)
SET @Text = SUBSTRING(@Text,8,LEN(@Text))
SET @Text = 'alter ' + @Text
END
SET @Text = REPLACE(@Text,@OldDBName,@NewDBName)
SET @SQL = @SQL + @Text
SET @y = @y + 1
END
DROP TABLE #ProcText
SELECT @procname
BEGIN TRY
EXEC (@SQL)
END TRY
BEGIN CATCH
SELECT N'出错:' + @procname,@SQL
END CATCH
SET @i = @i + 1
END
DROP TABLE #tttt
GO
--这里用到了这个函数
Create FUNCTION [dbo].[f_group_split]
(
@SourceSql VARCHAR(8000),
@type NVARCHAR(100)
)
RETURNS @temp TABLE
(
group_code VARCHAR(1000)
)
AS
BEGIN
DECLARE @i INT;
SET @SourceSql = RTRIM(LTRIM(@SourceSql));
SET @i = CHARINDEX(@type, @SourceSql);
WHILE @i >= 1
BEGIN
INSERT @temp
VALUES ( LEFT(@SourceSql, @i - 1) );
SET @SourceSql = SUBSTRING(@SourceSql, @i + 1,
LEN(@SourceSql) - @i);
SET @i = CHARINDEX(@type, @SourceSql);
END;
IF @SourceSql <> @type
INSERT @temp
VALUES ( @SourceSql );
RETURN;
END;
GO
第二个问题:
如果有使用共享数据源,这是最简单的,那么只需要更换那个共享的数据源即可。那么假如在没有使用共享数据源的情况下,要如何批量替换报表的链接数据源呢。
这部分可以看本人另外一篇文章,SSRS SQL语句批量替换报表的数据源链接
处理完这两个问题之后,还原的数据库已经可以独立使用。只要配置进SSRS的配置管理器里面就可以了。