首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

关于存储过程返回的结果集读取的有关问题

2013-10-14 
关于存储过程返回的结果集读取的问题之前做了一个系统,这个系统的每个客户都是使用一个独立的数据库(所有

关于存储过程返回的结果集读取的问题
之前做了一个系统,这个系统的每个客户都是使用一个独立的数据库(所有数据库都放在同一个服务器上)
现在要做一个销售方的后台管理系统(可以跨数据库进行查询,主要是用于延长某客户的系统使用期限)

我在 master 表上面写了一个存储过程:

CREATE PROCEDURE [dbo].sp_prescription_info
AS
BEGIN
    SET NOCOUNT ON

    CREATE TABLE #dbInfo (
        [DB_ID] SMALLINT,
        [DB_NAME] SYSNAME,
        DB_UID SYSNAME,
        DB_CRDATE DATETIME,
        DB_SIZE NVARCHAR(13),
        DB_VDATE DATETIME
    )

    DECLARE @sid VARBINARY(85)
    DECLARE @name SYSNAME
    DECLARE @dbid SMALLINT
    DECLARE @crdate DATETIME
    DECLARE curDB CURSOR FOR
        SELECT name, dbid, crdate, sid FROM sysdatabases WHERE dbid > 4

    --创建临时表, 用于获取数据库大小
    CREATE TABLE #dbHelp (
        name NVARCHAR(24),
        db_size NVARCHAR(13),
        owner NVARCHAR(24),
        dbid SMALLINT,
        created CHAR(11),
        status VARCHAR(340),
        compatibility_level TINYINT
    )
    INSERT INTO #dbHelp EXEC sp_helpdb

    DECLARE @sql NVARCHAR(1000)

    OPEN curDB
    FETCH curDB INTO @name, @dbid, @crdate, @sid

    WHILE (@@FETCH_STATUS = 0)
    BEGIN
        --检查数据库是否包含特定表及列
        DECLARE @isTargetDB INT
        SET @sql = N'SELECT @isTargetDB = COUNT(*) FROM ' + @name + '.dbo.syscolumns db
            WHERE (name = ''CFG_TYPE'' OR name = ''CFG_VALID'') AND id = (
                SELECT db.id FROM ' + @name + '.dbo.sysobjects db
                WHERE db.name = ''Config'' AND xtype = ''U'')'
        EXEC sp_executesql @sql, N'@isTargetDB INT OUT', @isTargetDB OUT

        PRINT @isTargetDB
        IF (@isTargetDB = 2)
        BEGIN
            --检查该列中的值是否符合要求
            DECLARE @type NVARCHAR(15)
            DECLARE @vdate NVARCHAR(50)
            SET @sql = N'SELECT @type = db.CFG_TYPE, @vdate = db.CFG_VALID FROM ' + @name + '.dbo.Config db'
            EXEC sp_executesql @sql, N'@type NVARCHAR(15) OUT, @vdate DATETIME OUT', @type OUT, @vdate OUT

            IF @type = 'Prescription' AND ISDATE(@vdate) = 1
            BEGIN
                DECLARE @uid SYSNAME SET @uid = N''
                SELECT @uid = loginname FROM syslogins WHERE sid = @sid

                INSERT INTO #dbInfo SELECT @dbid, @name, @uid, @crdate, db_size, @vdate FROM #dbHelp WHERE name = @name
            END
        END

        FETCH curDB INTO @name, @dbid, @crdate, @sid
    END

    CLOSE curDB
    DEALLOCATE curDB

    DROP TABLE #dbHelp

    SELECT * FROM #dbInfo



    DROP TABLE #dbInfo
END
GO



这个存储过程主要是用于判断服务器中的所有数据库是否该系统所使用的数据库,如果是就把该数据库的信息插入到一个临时表中,然后返回这个临时表

我在程序里调这个存储过程:
// 执行存储过程
int CELConn::ExecuteStored(LPCTSTR pszStoredName, _variant_t *pParamVal, _variant_t **pResult /*= NULL*/, HRECORD *pRecord /*= NULL*/)
{
    if (m_hConn == NULL || pszStoredName == NULL) return -1;

    _ConnectionPtr pConn = *(_ConnectionPtr *)m_hConn;
    _RecordsetPtr *pRecordset = NULL;

    int nRtnCount = 0;
    BOOL *pbRtnParam = NULL;

    CONNTRY
        _CommandPtr pCmd = NULL;
        HRESULT hr = pCmd.CreateInstance(__uuidof(Command));
        if (hr != S_OK) return -1;

        pCmd->ActiveConnection = pConn;
        pCmd->CommandText = (_bstr_t)pszStoredName;
        pCmd->CommandType = adCmdStoredProc;
        pCmd->Parameters->Refresh();

        long lParamCount = pCmd->Parameters->GetCount();
        pbRtnParam = new BOOL[lParamCount];
        ::memset(pbRtnParam, 0, sizeof(BOOL) * lParamCount);

        for (long i = 0; i < lParamCount; i++)
        {
            _ParameterPtr pParam = pCmd->Parameters->GetItem(i);
            ParameterDirectionEnum pde = pParam->Direction;
            if (pde == adParamOutput || pde == adParamReturnValue || pde == adParamInputOutput)
            {
                nRtnCount++;
                pbRtnParam[i] = TRUE;
            }

            if (pParamVal[i].vt != VT_ERROR)
                pParam->Value = pParamVal[i];
        }

        pRecordset = new _RecordsetPtr;
        (*pRecordset).CreateInstance(__uuidof(Recordset));

        *pRecordset = pCmd->Execute(NULL, NULL, adCmdStoredProc);

// 这里返回的结果集,是关闭状态的,所以无法获取数据
// 但是在 SQL 查询分析器 上面调用这个存储过程,是有数据返回的
        if ((*pRecordset)->GetState() == adStateClosed)
            _ReleaseRecord((HRECORD &)pRecordset);

        if (nRtnCount >= 0 && pResult != NULL)
        {
            int nCount = 0;
            _variant_t *pRtn = new _variant_t[nRtnCount];
            for (long i = 0; i < lParamCount; i++)
            {
                if (pbRtnParam[i])
                {
                    pRtn[nCount] = pCmd->Parameters->GetItem(i)->Value;
                    nCount++;
                }
            }

            *pResult = pRtn;
        }
    CONNCATCH(
        nRtnCount = -1;
        SetLastError(e.Error());

        _ReleaseRecord((HRECORD &)pRecordset);
    )



    if (pbRtnParam != NULL) delete[] pbRtnParam;
    if (pRecord != NULL) *pRecord = (HRECORD)pRecordset;

    return nRtnCount;
}

// 调用
    _variant_t *pvar = NULL;
    HRECORD hRecord = NULL;
    int nRtn = ExecuteStored(_T("sp_prescription_info"), &vtMissing, &pvar, &hRecord);
    if (nRtn == -1 || pvar == NULL || hRecord == NULL)
    {
        if (pvar != NULL) delete[] pvar;
        if (hRecord != NULL) _ReleaseRecord(hRecord);
        return NULL;
    }



详细问题描述可以看看注释部分,这个问题如何处理?

注:HRECORD 只是一个 _RecordsetPtr 的指针定义(因为数据库连接我是做成一个独立 DLL)
连接数据库的用户默认表是 master,且拥有响应的权限
[解决办法]
弄好了吗?我来蹭个分。
[解决办法]
应该是帐号权限问题。

sa 帐号 EXEC sp_helpdb 能看到所有的数据库;
普通帐号 EXEC sp_helpdb 只能看到有权限访问的数据库。

还有 SELECT ... FROM sysdatabases
最好改成 SELECT ... FROM master..sysdatabases
[解决办法]
你的帐号对“每个客户都是使用的独立的数据库”是否都有访问权限?

热点排行