Usar matrizes de parâmetros

Para usar matrizes de parâmetros, o aplicativo chama SQLSetStmtAttr com um argumento Attribute de SQL_ATTR_PARAMSET_SIZE para especificar o número de conjuntos de parâmetros. Ele chama SQLSetStmtAttr com um argumento Attribute de SQL_ATTR_PARAMS_PROCESSED_PTR para especificar o endereço de uma variável na qual o driver pode retornar o número de conjuntos de parâmetros processados, incluindo conjuntos de erros. Ele chama SQLSetStmtAttr com um argumento Attribute de SQL_ATTR_PARAM_STATUS_PTR para apontar para uma matriz na qual retornar informações de status para cada linha de valores de parâmetro. O driver armazena esses endereços na estrutura que ele mantém para a instrução.

Observação

No ODBC 2.x, SQLParamOptions foi chamado para especificar diversos valores para um parâmetro. No ODBC 3.x, a chamada para SQLParamOptions foi substituída por chamadas para SQLSetStmtAttr para definir os atributos SQL_ATTR_PARAMSET_SIZE e SQL_ATTR_PARAMS_PROCESSED_ARRAY.

Antes de executar a instrução, o aplicativo define o valor de cada elemento de cada matriz associada. Quando a instrução é executada, o driver usa as informações armazenadas para recuperar os valores de parâmetro e enviá-los para a fonte de dados. Se possível, o driver deve enviar esses valores como matrizes. Embora a melhor forma de implementar o uso de matrizes de parâmetros seja executando a instrução SQL com todos os parâmetros na matriz com uma só chamada para a fonte de dados, esse recurso não está amplamente disponível em DBMSs atualmente. Porém, os drivers podem simulá-lo executando uma instrução SQL várias vezes, cada uma com um só conjunto de parâmetros.

Antes de um aplicativo usar matrizes de parâmetros, ele deve ter certeza de que eles são compatíveis com os drivers usados pelo aplicativo. Há duas maneiras de fazer isso:

  • Use apenas drivers que sabidamente são compatíveis com matrizes de parâmetros. O aplicativo pode codificar os nomes desses drivers, ou o usuário pode ser instruído a usar somente esses drivers. Aplicativos personalizados e aplicativos verticais costumam usar um conjunto limitado de drivers.

  • Verifique se há suporte para matrizes de parâmetros em tempo de execução. Um driver dará suporte a matrizes de parâmetros se for possível definir o atributo de instrução SQL_ATTR_PARAMSET_SIZE como um valor maior que 1. Aplicativos genéricos e aplicativos verticais costumam verificam o suporte a matrizes de parâmetros em tempo de execução.

É possível determinar a disponibilidade de contagens de linhas e conjuntos de resultados na execução parametrizada chamando SQLGetInfo com as opções SQL_PARAM_ARRAY_ROW_COUNTS e SQL_PARAM_ARRAY_SELECTS. Para instruções INSERT, UPDATE e DELETE, a opção SQL_PARAM_ARRAY_ROW_COUNTS indica se as contagens de linhas individuais (uma para cada conjunto de parâmetros) estão disponíveis (SQL_PARC_BATCH) ou se as contagens de linha são acumuladas em uma (SQL_PARC_NO_BATCH). Para instruções SELECT, a opção SQL_PARAM_ARRAY_SELECTS indica se um conjunto de resultados está disponível para cada conjunto de parâmetros (SQL_PAS_BATCH) ou se apenas um conjunto de resultados está disponível (SQL_PAS_NO_BATCH). Se o driver não permitir a execução de instruções geradoras de conjunto de resultados com uma matriz de parâmetros, SQL_PARAM_ARRAY_SELECTS retornará SQL_PAS_NO_SELECT. A possibilidade de usar matrizes de parâmetros com outros tipos de instruções depende da fonte de dados, especialmente porque o uso de parâmetros nessas instruções seria específico da fonte de dados e não seguiria a gramática SQL ODBC.

A matriz para a qual o atributo de instrução SQL_ATTR_PARAM_OPERATION_PTR aponta pode ser usada para ignorar linhas de parâmetros. Se um elemento da matriz estiver definido como SQL_PARAM_IGNORE, o conjunto de parâmetros correspondente a esse elemento será excluído da chamada SQLExecute ou SQLExecDirect. A matriz para a qual o SQL_ATTR_PARAM_OPERATION_PTR aponta é alocada e preenchida pelo aplicativo e lida pelo driver. Se as linhas para as quais foi efetuado fetch forem usadas como parâmetros de entrada, os valores da matriz de status de linha poderão ser usados na matriz de operação de parâmetro.

Processamento de erros

Caso ocorra um erro durante a execução da instrução, a função de execução retornará um erro e definirá a variável de número de linha como o número da linha que contém o erro. Depende da fonte de dados se todas as linhas, exceto o conjunto de erros, são executadas ou se todas as linhas antes (mas não depois) do conjunto de erros são executadas. Como ele processa conjuntos de parâmetros, o driver define o buffer especificado pelo atributo da instrução SQL_ATTR_PARAMS_PROCESSED_PTR como o número da linha que está sendo processada no momento. Se todos os conjuntos, exceto o conjunto de erros, forem executados, o driver definirá esse buffer como SQL_ATTR_PARAMSET_SIZE depois do processamento de todas as linhas.

Se o atributo da instrução SQL_ATTR_PARAM_STATUS_PTR tiver sido definido, SQLExecute ou SQLExecDirect retornará a matriz de status do parâmetro, que fornece o status de cada conjunto de parâmetros. A matriz de status do parâmetro é alocada pelo aplicativo e preenchida pelo driver. Seus elementos indicam se a instrução SQL foi executada com êxito para a linha de parâmetros ou se houve um erro ao processar o conjunto de parâmetros. Se tiver ocorrido um erro, o driver definirá o valor correspondente na matriz de status do parâmetro como SQL_PARAM_ERROR e retornará SQL_SUCCESS_WITH_INFO. O aplicativo pode verificar a matriz de status para determinar as linhas que foram processadas. Usando o número da linha, o aplicativo em geral pode corrigir o erro e retomar o processamento.

O modo como a matriz de status do parâmetro é usada é determinado pelas opções SQL_PARAM_ARRAY_ROW_COUNTS e SQL_PARAM_ARRAY_SELECTS retornadas por uma chamada para SQLGetInfo. Para instruções INSERT, UPDATE e DELETE, a matriz de status do parâmetro será preenchida com informações de status se SQL_PARC_BATCH for retornado para SQL_PARAM_ARRAY_ROW_COUNTS, mas não se SQL_PARC_NO_BATCH for retornado. Para instruções SELECT, a matriz de status do parâmetro será preenchida se SQL_PAS_BATCH for retornado para SQL_PARAM_ARRAY_SELECT, mas não se SQL_PAS_NO_BATCH ou SQL_PAS_NO_SELECT for retornado.

Parâmetros de dados em execução

Se qualquer um dos valores na matriz de comprimento/indicador for SQL_DATA_AT_EXEC ou o resultado da macro SQL_LEN_DATA_AT_EXEC(length), os dados desses valores serão enviados com SQLPutData da maneira usual. Os seguintes aspectos desse processo merecem um comentário especial porque não são imediatamente óbvios:

  • Quando o driver retorna SQL_NEED_DATA, ele precisa definir o endereço da variável de número de linha para a linha para a qual ele precisa de dados. Como no caso de valor único, o aplicativo não pode fazer suposições sobre a ordem em que o driver solicitará valores de parâmetro dentro de um só conjunto de parâmetros. Se ocorrer um erro na execução de um parâmetro de dados em execução, o buffer especificado pelo atributo da instrução SQL_ATTR_PARAMS_PROCESSED_PTR será definido como o número da linha na qual o erro ocorreu, o status da linha na matriz de status de linha especificada pelo atributo da instrução SQL_ATTR_PARAM_STATUS_PTR será definido como SQL_PARAM_ERROR e a chamada para SQLExecute, SQLExecDirect, SQLParamData ou SQLPutData retornará SQL_ERROR. O conteúdo desse buffer será indefinido se SQLExecute, SQLExecDirect ou SQLParamData retornar SQL_STILL_EXECUTING.

  • Como o driver não interpreta o valor no argumento ParameterValuePtr de SQLBindParameter para parâmetros de dados em execução, se o aplicativo fornecer um ponteiro para uma matriz, SQLParamData não extrairá e retornará um elemento dessa matriz para o aplicativo. Em vez disso, ele retornará o valor escalar fornecido pelo aplicativo. Isso significa que o valor retornado por SQLParamData não basta para especificar o parâmetro para o qual o aplicativo precisa enviar dados, o aplicativo também precisa considerar o número de linha atual.

    Quando somente alguns dos elementos de uma matriz de parâmetros são parâmetros de dados em execução, o aplicativo deve passar o endereço de uma matriz em ParameterValuePtr que contém elementos para todos os parâmetros. Essa matriz costuma ser interpretada para os parâmetros que não são parâmetros de dados em execução. Para os parâmetros de dados em execução, o valor que SQLParamData fornece ao aplicativo, que normalmente poderia ser usado para identificar os dados que o driver está solicitando nesta ocasião, é sempre o endereço da matriz.