Como passar uma matriz para um procedimento armazenado do SQL Server?
Por exemplo, eu tenho uma lista de funcionários. Eu quero usar esta lista como uma tabela e juntá-la a outra tabela. Mas a lista de funcionários deve ser passada como parâmetro em C #.
c#
sql-server
tsql
stored-procedures
Sergey
fonte
fonte
Respostas:
SQL Server 2008 (ou mais recente)
Primeiro, no seu banco de dados, crie os dois objetos a seguir:
Agora no seu código C #:
SQL Server 2005
Se você estiver usando o SQL Server 2005, eu ainda recomendaria uma função de divisão sobre XML. Primeiro, crie uma função:
Agora seu procedimento armazenado pode ser apenas:
E no seu código C # você só precisa passar a lista como
'1,2,3,12'
...Acho que o método de passar por parâmetros com valor de tabela simplifica a capacidade de manutenção de uma solução que a utiliza e, muitas vezes, aumenta o desempenho em comparação com outras implementações, incluindo XML e divisão de cadeias.
As entradas são claramente definidas (ninguém precisa adivinhar se o delimitador é uma vírgula ou ponto-e-vírgula) e não temos dependências de outras funções de processamento que não são óbvias sem inspecionar o código para o procedimento armazenado.
Comparado às soluções que envolvem o esquema XML definido pelo usuário em vez de UDTs, isso envolve um número semelhante de etapas, mas, na minha experiência, o código é muito mais simples de gerenciar, manter e ler.
fonte
SELECT [colA] FROM [MyTable] WHERE [Id] IN (SELECT [Id] FROM @ListOfIds)
.Com base na minha experiência, ao criar uma expressão delimitada a partir dos IDs dos funcionários, há uma solução complicada e agradável para esse problema. Você só deve criar uma expressão de cadeia como
';123;434;365;'
em que123
,434
e365
algumas employeeIDs. Chamando o procedimento abaixo e passando essa expressão para ele, você pode buscar os registros desejados. Você pode facilmente associar a "outra tabela" a esta consulta. Esta solução é adequada em todas as versões do SQL server. Além disso, em comparação com o uso de variável de tabela ou tabela temporária, é uma solução muito mais rápida e otimizada.fonte
Use um parâmetro com valor de tabela para seu procedimento armazenado.
Quando você o passa do C #, adiciona o parâmetro ao tipo de dados SqlDb.Structured.
Consulte aqui: http://msdn.microsoft.com/en-us/library/bb675163.aspx
Exemplo:
fonte
Você precisa passá-lo como um parâmetro XML.
Edit: código rápido do meu projeto para ter uma idéia:
Então você pode usar a tabela temporária para se juntar às suas tabelas. Definimos arrayOfUlong como um esquema XML interno para manter a integridade dos dados, mas você não precisa fazer isso. Eu recomendo usá-lo, então aqui está um código rápido para garantir que você sempre obtenha um XML com longs.
fonte
O contexto é sempre importante, como o tamanho e a complexidade da matriz. Para listas pequenas e médias, várias das respostas postadas aqui são excelentes, embora alguns esclarecimentos devam ser feitos:
text()
Função XML Para obter mais informações (análise de desempenho) sobre o uso de XML para dividir listas, consulte "Usando XML para passar listas como parâmetros no SQL Server", de Phil Factor.DataTable
significa duplicar os dados na memória à medida que são copiados da coleção original. Portanto, o uso doDataTable
método de transmissão em TVPs não funciona bem para conjuntos maiores de dados (ou seja, não é bem dimensionado).DataTable
método TVP, o XML não é escalável, pois mais do que duplica o tamanho dos dados na memória, pois precisa levar em conta adicionalmente a sobrecarga do documento XML.Com tudo isso dito, se os dados que você está usando são grandes ou ainda não muito grandes, mas crescem consistentemente, o
IEnumerable
método TVP é a melhor opção, pois transmite os dados para o SQL Server (como oDataTable
método), MAS NÃO requer qualquer duplicação da coleção na memória (diferente de qualquer outro método). Publiquei um exemplo do código SQL e C # nesta resposta:Passar dicionário para procedimento armazenado T-SQL
fonte
Não há suporte para a matriz no servidor sql, mas existem várias maneiras pelas quais você pode passar a coleção para um processo armazenado.
O link abaixo pode ajudá-lo
passando a coleção para um procedimento armazenado
fonte
Eu estive pesquisando todos os exemplos e respostas de como passar qualquer array para o servidor sql sem o incômodo de criar um novo tipo de tabela, até encontrar esse link , abaixo é como o apliquei ao meu projeto:
--O código a seguir obtém uma matriz como parâmetro e insere os valores dessa matriz em outra tabela
Espero que goste
fonte
@s
for CSV, seria mais rápido simplesmente dividir isso (por exemplo, INSERIR EM ... SELECIONAR NA FunçãoFunção). A conversão para XML é mais lenta que o CLR e o XML baseado em atributos é muito mais rápido. E esta é uma lista simples, mas a transmissão em XML ou TVP também pode lidar com matrizes complexas. Não sabe ao certo o que é ganho, evitando uma tarefa simples e únicaCREATE TYPE ... AS TABLE
.Isso irá ajudá-lo. :) Siga os próximos passos,
Copiar Cole o seguinte código como ele é, ele criará a Função que converte a String em Int
Crie o seguinte procedimento armazenado
Executar este SP. Usando
exec sp_DeleteId '1,2,3,12'
isso, é uma sequência de IDs que você deseja excluir,Você converte sua matriz em string em C # e a passa como um parâmetro de procedimento armazenado
Isso excluirá várias linhas. Tudo de bom
fonte
Levei muito tempo para descobrir isso, por isso, caso alguém precise ...
Isso é baseado no método SQL 2005 na resposta de Aaron e usando sua função SplitInts (acabei de remover o parâmetro delim, pois sempre usarei vírgulas). Estou usando o SQL 2008, mas queria algo que funcionasse com conjuntos de dados digitados (XSD, TableAdapters) e sei que parâmetros de string funcionam com eles.
Eu estava tentando fazer com que a função dele funcionasse em uma cláusula do tipo "where in (1,2,3)" e não tendo sorte no caminho direto. Então, criei uma tabela temporária primeiro e depois fiz uma junção interna em vez de "where in". Aqui está o meu exemplo de uso: no meu caso, eu queria obter uma lista de receitas que não contêm certos ingredientes:
fonte
Como outros observaram acima, uma maneira de fazer isso é converter sua matriz em uma cadeia de caracteres e depois dividir a cadeia dentro do SQL Server.
No SQL Server 2016, existe uma maneira interna de dividir seqüências de caracteres chamada
Ele retorna um conjunto de linhas que você pode inserir na sua tabela temporária (ou tabela real).
produziria:
Se você quiser ficar mais chique:
forneceria os mesmos resultados acima (exceto que o nome da coluna é "número depois"), mas classificado. Você pode usar a variável de tabela como qualquer outra tabela, para poder associá-la facilmente a outras tabelas no banco de dados, se desejar.
Observe que a instalação do SQL Server deve estar no nível de compatibilidade 130 ou superior para que a
STRING_SPLIT()
função seja reconhecida. Você pode verificar seu nível de compatibilidade com a seguinte consulta:A maioria dos idiomas (incluindo C #) possui uma função "join" que você pode usar para criar uma string a partir de uma matriz.
Então você passa
sqlparam
como seu parâmetro para o procedimento armazenado acima.fonte
fonte