如何将数据从MDX OLAP多维数据集中“拉”到标准SQL Server表中?

如何将数据从MDX OLAP多维数据集中“拉”到标准SQL Server表中?,sql,sql-server,olap-cube,Sql,Sql Server,Olap Cube,我已经获得了对多维数据集的访问权,我需要知道是否可以设置一个存储过程来连接到多维数据集并通过MDX查询检索内容。 我需要这样做,以避免必须通过PowerPivot从Management Studio或Excel导出数据。 我对多维数据集/olap查询非常陌生,所以请原谅我的天真。最简单的方法是创建一个链接到多维数据集的服务器,然后插入..从OPENQUERY中选择 此选项在这方面有限制 它对MDX查询有8000个字符的约束 必须为每个数据库手动创建链接服务器 当结果为空时,需要处理特殊代码 结果

我已经获得了对多维数据集的访问权,我需要知道是否可以设置一个存储过程来连接到多维数据集并通过MDX查询检索内容。 我需要这样做,以避免必须通过PowerPivot从Management Studio或Excel导出数据。
我对多维数据集/olap查询非常陌生,所以请原谅我的天真。

最简单的方法是创建一个链接到多维数据集的服务器,然后插入..从OPENQUERY中选择

此选项在这方面有限制

它对MDX查询有8000个字符的约束 必须为每个数据库手动创建链接服务器 当结果为空时,需要处理特殊代码 结果集列ntext(列)和NVARCH4000(行)中的数据类型过多
高级选项是ExecuteLap CLR存储过程

如果您选择使用OPENQUERY最简单的方法,但有Brian指定的限制,则以下过程可能很方便:

    /* 
PARAMS:
    @mdx: mdx statement
    @mdx_columns: specifies the mdx columns to retrieve from the executed mdx
    @linkedServer: linked server to be used
    @resultsTable: temporary table to hold results from mdx
    @resultsCols: if only some columns should be filled in @resultsTable, specify them here (e.g. '(col1, col2, ... )' )
    @expectedColCount: expected column count for mdx result. If actual column count is different from the expected count, no data is filled in
    @actualColCount: actual column count. Specify NULL if not interesed in this value
    @Debug: outputs debug info
*/
ALTER PROCEDURE [dbo].[exec_mdx_over_linked_server] (
    @mdx NVARCHAR(MAX),
    @mdx_columns NVARCHAR(1024) = '*',
    @linkedServer VARCHAR(64),
    @resultsTable VARCHAR(64),
    @resultsCols VARCHAR(1024) = '',
    @expectedColCount SMALLINT,
    @actualColCount SMALLINT = NULL OUTPUT,
    @Debug BIT = 0
)
AS
BEGIN
    SET NOCOUNT ON

    if (@Debug = 1)
        PRINT 'Started exec_mdx_over_linked_server procedure for populating ' + @resultsTable

    IF LEN(@MDX)>8000 RAISERROR ('MDX too long for openquery (exec_mdx_over_linked_server)', 
                                16,
                                1);

    declare @SQL NVARCHAR(MAX)

    IF (@Debug = 1)
    BEGIN
        -- getting results from mdx
        SET @SQL = 'SELECT ''Mdx results for ' + @resultsTable + ''' AS ''Mdx results'', ' + '*' + ' 
            FROM OPENQUERY(' + @linkedServer + ', ''' + @mdx + ''')';
        IF LEN(@SQL)>8000 RAISERROR ('MDX too long for openquery (exec_mdx_over_linked_server)', 
                                    16,
                                    1);
        EXEC (@SQL)
    END

    SET @SQL = '
        SELECT ' + '*' + ' INTO #resultsWithWeirdNameToAvoidTempCollisions
        FROM OPENQUERY(' + @linkedServer + ', ''' + @mdx + ''');

        SELECT @colCount = COUNT(*)
        FROM tempdb.sys.columns
        WHERE object_id = object_id(''tempdb..#resultsWithWeirdNameToAvoidTempCollisions'');

        if (@colCount = @expectedColCount)
            INSERT INTO ' + @resultsTable + @resultsCols + '
            SELECT ' + @mdx_columns +  ' FROM #resultsWithWeirdNameToAvoidTempCollisions'


    IF LEN(@SQL)>8000 RAISERROR ('MDX too long for openquery (exec_mdx_over_linked_server)', 
                                    16,
                                    1);

    if (@Debug = 1)
        PRINT 'dbo.exec_mdx_over_linked_server SQL = ' + @SQL

    DECLARE @colCount INT
    EXECUTE sp_executesql @SQL, N'@expectedColCount SMALLINT, @ColCount SMALLINT OUTPUT', @expectedColCount = @expectedColCount, @colCount = @actualColCount OUTPUT

    if (@Debug = 1)
    BEGIN
        PRINT '@expectedColCount = '; PRINT @expectedColCount
        PRINT '@actualColCount = '; PRINT @actualColCount
    END

    -- correction for small float numbers (< 10E-10)

    DECLARE @UpdateSql NVARCHAR(MAX) = N''
    DECLARE @SmallThreshold FLOAT = 0.00000000001


    SELECT @UpdateSql += '
                            UPDATE ' + @resultsTable + ' 
                            SET ' + QUOTENAME(COLUMN_NAME) + ' = 0 
                            WHERE TRY_CONVERT (FLOAT, ' + QUOTENAME(COLUMN_NAME) + ') IS NOT NULL
                                                 AND ABS(' + QUOTENAME(COLUMN_NAME) + ') < ' + CAST(@SmallThreshold AS NVARCHAR(30))
    FROM tempdb.INFORMATION_SCHEMA.COLUMNS with(NOLOCK)
    -- WHERE table_name like @resultsTable + '[_][_][_]%'
    -- changed, in order not to take into consideration objects from other spids
    WHERE table_name = object_name(object_id('tempdb..' + @resultsTable), (select database_id from sys.databases where name = 'tempdb'))

    IF (@Debug = 1)
    BEGIN
        PRINT '@UpdateSql = '; PRINT @UpdateSql;
    END

    EXEC (@UpdateSql);

END
它具有以下优点:

处理接收到的结果不具有预期列时的情况—不执行任何操作 对非常小的数字执行一些舍入这可能会发生,因为多维数据集只知道处理浮点数 所有mdx语句都经过一个过程 在分析时,我注意到,通过过程执行与直接针对analysis server执行相比,开销约为100毫秒


.NET开发人员可以使用framework,它允许运行参数化查询,并且开销较小。

生成SSIS包并安排它不是一个选项?现在是了,非常感谢您朝着可能正确的方向推动。