2014-12-10 3 views
1

Я хочу подвести итоги из нескольких баз данных. На данный момент у меня есть три базы данных: SPA_PROD, SPB_PROD и SPC_PROD.Суммировать значения из баз данных и параметризовать их. [SQL Server]

Мой SQL-запрос:

IF EXISTS (SELECT * 
      FROM sys.objects 
      WHERE object_id = OBJECT_ID(N'[dbo].[TESTSUM]') 
        AND TYPE IN (N'P',N'PC')) 
    DROP PROCEDURE [dbo].[TESTSUM] 
GO 

CREATE PROC TESTSUM 
AS 
BEGIN 
    DECLARE @dbName  SYSNAME, 
      @ObjectSUM INT, 
      @d datetime 

    SET @d = '20141113' 

    DECLARE @SQL NVARCHAR(MAX) 

    DECLARE @DBObjectStats TABLE (
            --DBName SYSNAME, 
            DBObjects INT) 

    DECLARE curAllDBs CURSOR FOR 
     SELECT name 
     FROM MASTER.dbo.sysdatabases 
     WHERE name like '%PROD' 
     ORDER BY name 

    OPEN curAllDBs 

    FETCH curAllDBs INTO @dbName 

    WHILE (@@FETCH_STATUS = 0) -- db loop 
    BEGIN 
     --SQL QUERY 
     SET @SQL = 'select @dbObjects = sum(doctotal) from ' + 
        QuoteName(@dbName) + '..Invoice 
         where DocDate = ''' + cast(@d as varchar(25)) + '''' 

     PRINT @SQL -- Debugging 

     EXEC sp_executesql @SQL, N'@dbObjects int output', 
      @dbObjects = @ObjectSUM output 

     INSERT @DBObjectStats 
      SELECT @ObjecSUM 

     FETCH curAllDBs INTO @dbName 
    END 

    CLOSE curAllDBs 
    DEALLOCATE curAllDBs 

    -- Return results 
    SELECT sum(DBObjects) [InvoiceSUM] FROM @DBObjectStats 
END 
GO 

-- Execute stored procedure 
EXEC TESTSUM 
GO 

И эта работа совершенна и дает мне правильную сумму от всех моих DBS:. 120 000 $ (25 000 от SPA_PROD, 95 000 SPC_PROD и 0 (NULL) от SPB_PROD

То, что я хочу сделать:

Я хотел бы параметризуем, что позволяет мне выбрать дату и базы данных Например, я хочу, чтобы выбрать SPA_PROD и SPB_PROD с датой 2014-01-0. 1 в другом случае я хочу, чтобы все базы данных (SPA + SPB + SPC с другой датой.

Возможно ли это? Есть идеи?

Я могу использовать все, что дает мне SQL Server 2012 и T-SQL. Может быть, эта технология предлагает мне самый простой способ сделать это.

Я также использую SAP Crystal Reports для преобразования SQL-вывода в красивый отчет.

Извините за мой английский, и я попытался описать вам свою проблему, насколько мог. Если вам нужна дополнительная информация, которая поможет вам помочь мне -> спросите меня :).

ответ

0

Вы можете создать пользовательский тип таблицы:

CREATE TYPE DBTable AS TABLE 
(
    DBName VARCHAR(128) 
); 

Вы можете использовать его в качестве входного параметра хранимой процедуры. Как и параметр даты.

CREATE PROCEDURE TESTSUM 
    @Databases DBTable READONLY 
    ,@Date DATETIME 
AS 
BEGIN 
... 
... 
... 

Вы называете это так:

DECLARE @T AS DBTable; 
DECLARE @D AS DATETIME = GETDATE(); 
INSERT INTO @T VALUES ('DB1', 'DB2', 'DB3') 
EXEC TESTSUM @T, @D 
0

может быть, вместо

SELECT name 
     FROM MASTER.dbo.sysdatabases 

использование

SELECT name 
     FROM #temptable 

и вставить в #temptable конкретные дб вы хотите

0

Используя ваш пример, я изменил его, чтобы принять строку имен базы данных (сгенерированную с помощью Crystal Reports select action). Затем передача этой строки с указанной датой для первой проверки базы данных существует, и если в Интернете добавить требуемое предложение union к сгенерированному SQL-коду.

CREATE PROCEDURE TESTSUM 
    @DbNameS NVARCHAR(max) 
    ,@Date DATETIME 
AS 
BEGIN 
    DECLARE @SQL NVARCHAR(MAX) = '' 

    /* ADD EXTRA ',' RO STRING ARRAY OF DATABASES */ 
    SET @DbNameS = @DbNameS + ','; 

    DECLARE @L INT = LEN(@DbNameS); 
    DECLARE @D INT = 0; 
    DECLARE @LD INT = 1; 
    DECLARE @DBF VARCHAR(50); 
    DECLARE @ACTIVE INT = 0; 

    /* START SQL QUERY */ 
    SET @SQL = 'SELECT SUM([InvoiceSUM]) AS [InvoiceSUM] FROM (SELECT '''' AS DB, 0.00 AS [InvoiceSUM]' + CHAR(13) 

    /* LOOP THROUGH EACH DBF NAME PASSED CHECKING IF VALID AND ONLINE */  
    WHILE @D < @L 
    BEGIN 
     SET @D = CHARINDEX(',', @DbNameS,@LD); 
     IF @LD != @D 
     BEGIN 
      SET @DBF = SUBSTRING(@DbNameS,@LD,@[email protected]) 
      /* VALIDATE DBF IS VALID AND ACTIVE */ 
      SELECT @ACTIVE = COUNT(*) FROM SYS.databases WHERE name = @DBF AND [state] = 0 
      IF @ACTIVE = 1 
      BEGIN 
       /* 
        BEGIN CODE TO UNION THE SUM RESULTS FOR EACH ACTIVE AND VALID DBF 
        TO MAKE IT WORK WITH SOME EXISTING DBF's ON MY SYSTEM I CHANGED THE SUMMARY CODE FOR TESTING  
       */ 
       SET @SQL = @SQL + 'UNION SELECT '''+ @DBF +''' AS DB, ISNULL(SUM(CAST(DVE AS DECIMAL(18,10))),0) AS [InvoiceSUM] FROM '+ @DBF + '.DBO.SO_MSTR WHERE CAST(RecordCreated AS DATE) = '''+ CAST(@Date AS VARCHAR(20)) + '''' + CHAR(13) 
      END; 
     END; 
     SET @LD = @D + 1; 
    END; 
    /* CLOSE OUT UNION SUMMARY QUERY */ 
    SET @SQL = @SQL + ') AS DATA' 

    /* OUTPUT RESULTS */ 
    EXEC SP_EXECUTESQL @SQL 
END; 

отчетов хрустальных бы эффективные порождающие этот код: EXEC TESTSUM 'SPA_PROD,SPB_PROD,SPC_PROD','12/09/2014'

Смежные вопросы