Usuário com melhor resposta
Transformar uma String em código.

Pergunta
-
O que quero fazer é o seguinte:
eu tenho um parâmentro chamado @valorX do tipo VARCHAR(MAX), aonde é atribuido algo do tipo : '1;2;3;4;5;6;7;8;9'
Eu queria que minha procedure fizesse o seguinte :
Pegar esse parâmetro @valorX e desmembralo, comparando a variável x com cada valor entre ";" do parâmetro, ficando assim:
Where
x = '1' OR x = '2' OR x='3' OR x='4' OR x='5' OR x='6' OR x='7' OR x='8' OR x='9'
Tem como fazer isso?
Respostas
-
Bom Dia,
Não sei se entendi bem, mas talvez o código abaixo o atenda:
Code BlockDECLARE
@strSQL VARCHAR(1000), @par VARCHAR(300)SET
@par = '1;2;3;4;5;6;7;8;9'SET
@strSQL = 'SELECT Alguma Coisa FROM Tabela'SET
@strSQL = @strSQL + ' WHERE 'SET
@par = REPLACE(@par,';',''' Or Campo = ''')SET
@par = LEFT(@par,LEN(@par)-9)SET
@par = 'Campo = ''' + @parSET
@strSQL = @strSQL + @par--PRINT @strSQL
EXEC
(@strSQL)[ ]s,
Gustavo
-
Bom dia,
Não pode usar o IN??
DECLARE
@valorX VARCHAR(max)SET
@valorX = '1;2;3;4;5;6;7;8;9'set
@valorX = replace(@valorX ,';',',')SELECT @valorX
where IN(@valorX)
Espero ter ajudado,
Abraço,
-
Renan,
Veja esta função que criei a algum tempo, já postei ela algumas vezes, vai resolver seu problema:
Code BlockCREATE
FUNCTION [dbo].[fnStringToInt] (@String VARCHAR(1000), @Separador CHAR(1))RETURNS
@Inteiros TABLE (IDs int)AS
BEGIN
DECLARE @Int INT IF PATINDEX ('%' + @Separador + '%', @String) = 0 INSERT INTO @Inteiros VALUES (@String) ELSE BEGIN WHILE PATINDEX ('%' + @Separador + '%', @String) > 0 BEGIN INSERT INTO @Inteiros VALUES (CONVERT (INT, SUBSTRING (@String, 1, PATINDEX ('%' + @Separador + '%', @String) - 1))) SET @String = SUBSTRING (@String, PATINDEX ('%' + @Separador + '%', @String) + 1, LEN(@String)) END INSERT INTO @Inteiros VALUES (@String) END RETURNEND
Para usar ela, faça da seguinte maneira:
Code BlockSELECT
CamposFROM
SuaTabelaWHERE
Campo IN (SELECT IDs FROM [dbo].[fnStringToInt] ('1;2;3;4;5;6', ';'))Ou pode até mesmo fazer um JOIN com o resultado da function.
Se tiver problemas, retorne.
Abraço
-
Claro, sem problemas,
O problema está sendo causado pela diferença no COLLATE, recomendo verificar o collate do campo que está sendo comparado para então fazer a mudança da função.
Por exemplo, se na coluna estiver sendo usado o collate "SQL_Latin1_General_CP1_CI_AI", faça assim:
Code BlockCREATE
FUNCTION [dbo].[fnStringToRef] (@String VARCHAR(1000), @Separador CHAR(1))RETURNS
@Valores TABLE (@Val VARCHAR (7) COLLATE SQL_Latin1_General_CP1_CI_AI)AS
BEGIN
. . .Ou, em último caso, faça assim:
Code BlockSELECT
* FROM Atendimento WHEREateSaida
COLLATE SQL_Latin1_General_CP1_CI_AI IN(SELECT IDs COLLATE SQL_Latin1_General_CP1_CI_AI FROM [dbo].[fnStringToRef] ('10/2005;05/2006', ';'))Mas, pessoalmente, prefiro a primeira opção por questões de desempenho.
Abraço!!
Todas as Respostas
-
Bom Dia,
Não sei se entendi bem, mas talvez o código abaixo o atenda:
Code BlockDECLARE
@strSQL VARCHAR(1000), @par VARCHAR(300)SET
@par = '1;2;3;4;5;6;7;8;9'SET
@strSQL = 'SELECT Alguma Coisa FROM Tabela'SET
@strSQL = @strSQL + ' WHERE 'SET
@par = REPLACE(@par,';',''' Or Campo = ''')SET
@par = LEFT(@par,LEN(@par)-9)SET
@par = 'Campo = ''' + @parSET
@strSQL = @strSQL + @par--PRINT @strSQL
EXEC
(@strSQL)[ ]s,
Gustavo
-
Bom dia,
Não pode usar o IN??
DECLARE
@valorX VARCHAR(max)SET
@valorX = '1;2;3;4;5;6;7;8;9'set
@valorX = replace(@valorX ,';',',')SELECT @valorX
where IN(@valorX)
Espero ter ajudado,
Abraço,
-
*@#&*!& BIXO!!!! TU ME AJUDO PRA !@#(*#@!)(*@# !!!!!!!!!!
Da vontade até de gritar aqui, vc me respondeu duas coisa, a primeira era sobre o desmembramento de string (sinto lhe informar que não é mais necessario graças a vc, ehehehehe)
Só pra vc ter uma idéia, eu tava criando vários parâmetros para serem passados para dentro da where da minha procedure...
Porém tudo oq eu precisava era que eu pudesse montar minha where via código e que pudesse passar toda ela via parâmetro na minha procedure, eu não sabia como transformar uma string em codigo, ou fazer ela ser executada.
Po bixo, tu me salvo mesmo.
Resumindo.... VLW CHAPOLA E GUSTAVO!!! -
-
Vlw chapola, mas olha só, não está dando certo sua query (pelo menos eu não consegui rodar), da erro... ao meu ver é pq fica mais ou menos assim:
DECLARE @valorX VARCHAR(max)
SET @valorX = '1;2;3;4;5;6;7;8;9'
set @valorX = replace(@valorX ,';',',')
SELECT * FROM [TABELA] vWHERE alor IN('1,2,3,4,5,6,7')
Ele vai ler 1,2,3,4,5,6,7 como se fosse uma variável. não?
-
-
-
cara,
Tira os Plic's o IN Plics = ' deixa ele dessa forma IN(1,2,3,4,5,6,7) e veja se funciona.
Esse é o problema, não consigo fazer isso.
Olha oq está acontecendo:
A procedure ficou assim :
DECLARE @valorX VARCHAR(max)
SET @valorX = '40;148'
SET @valorX = replace(@valorX ,';',',')
SELECT conContrato FROM Contratos
WHERE conContrato IN(@valorX)
Quando executo da o erro :
Msg 245, Level 16, State 1, Line 6
Conversion failed when converting the varchar value '40,148' to data type int. -
Boa Tarde,
Infelizmente a solução abaixo não irá funcionar:
DECLARE @valorX VARCHAR(max)
SET @valorX = '1;2;3;4;5;6;7;8;9'
set @valorX = replace(@valorX ,';',',')
SELECT * FROM [TABELA] WHERE valor IN('1,2,3,4,5,6,7')
Dessa forma ele procurará todos os registros cujo o valor é igual '1,2,3,4,5,6,7'. Essa condição não é semelhante a
WHERE valor IN(1,2,3,4,5,6,7)
Embora pareça ser uma pena, isso é necessário. Se alguém quisesse pesquisar o valor '1,2,3,4,5,6,7' e a consulta entendesse como um IN, não seria possível realizar essa busca. Esse raciocínio só irá funcionar, se você fizer uma construção dinâmica como a que eu havia sugerido.
[ ]s,
Gustavo
-
Exatamente Gustavo....
Porém não posso fazer uma construção dinâmica, pois estou usando report service e ele não consegue vincular procedures como a sua para algum relatório, pois ele não identifica os campos e etc...
Eu pensei em algo do tipo :
DECLARE @strSQL VARCHAR(1000), @par VARCHAR(300)
SET @par = '40,148'
SET @strSQL = 'SELECT conContrato FROM Gss_Contrato'
SET @strSQL = @strSQL + ' WHERE conContrato IN (' + @par + ')'
SELECT conContrato FROM (
EXEC(@strSQL)
)
Assim ele identificaria os campos de retorno, podendo essa procedure ser vinculada a um relatório. -
-
Renan,
Veja esta função que criei a algum tempo, já postei ela algumas vezes, vai resolver seu problema:
Code BlockCREATE
FUNCTION [dbo].[fnStringToInt] (@String VARCHAR(1000), @Separador CHAR(1))RETURNS
@Inteiros TABLE (IDs int)AS
BEGIN
DECLARE @Int INT IF PATINDEX ('%' + @Separador + '%', @String) = 0 INSERT INTO @Inteiros VALUES (@String) ELSE BEGIN WHILE PATINDEX ('%' + @Separador + '%', @String) > 0 BEGIN INSERT INTO @Inteiros VALUES (CONVERT (INT, SUBSTRING (@String, 1, PATINDEX ('%' + @Separador + '%', @String) - 1))) SET @String = SUBSTRING (@String, PATINDEX ('%' + @Separador + '%', @String) + 1, LEN(@String)) END INSERT INTO @Inteiros VALUES (@String) END RETURNEND
Para usar ela, faça da seguinte maneira:
Code BlockSELECT
CamposFROM
SuaTabelaWHERE
Campo IN (SELECT IDs FROM [dbo].[fnStringToInt] ('1;2;3;4;5;6', ';'))Ou pode até mesmo fazer um JOIN com o resultado da function.
Se tiver problemas, retorne.
Abraço
-
-
-
Se não fosse pedir muito, vc pode me ajudar com uma função que estou fazendo...
ela é basicamente a sua, mas ao invéz de INT, ela retorna uma tabela de VARCHAR(7)
Bom, eu ja testei ela, e funciono, mas quando tento usar ela assim:
SELECT *
FROM Atendimento
WHERE
ateSaida IN(SELECT IDs FROM [dbo].[fnStringToRef] ('10/2005;05/2006', ';'))
Minha função apresenta o seguinte erro :
Msg 468, Level 16, State 9, Line 19
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AI" and "SQL_Latin1_General_CP850_CI_AI" in the equal to operation.
Se eu coloco só :
SELECT IDs FROM [dbo].[fnStringToRef] ('10/2005;05/2006', ';')
ele traz numa boa, sem erros e sem nada, por isso presumo que o erro não esteja na função, e sim na comparação, mas não sei como resolver esse confito de collation -
Claro, sem problemas,
O problema está sendo causado pela diferença no COLLATE, recomendo verificar o collate do campo que está sendo comparado para então fazer a mudança da função.
Por exemplo, se na coluna estiver sendo usado o collate "SQL_Latin1_General_CP1_CI_AI", faça assim:
Code BlockCREATE
FUNCTION [dbo].[fnStringToRef] (@String VARCHAR(1000), @Separador CHAR(1))RETURNS
@Valores TABLE (@Val VARCHAR (7) COLLATE SQL_Latin1_General_CP1_CI_AI)AS
BEGIN
. . .Ou, em último caso, faça assim:
Code BlockSELECT
* FROM Atendimento WHEREateSaida
COLLATE SQL_Latin1_General_CP1_CI_AI IN(SELECT IDs COLLATE SQL_Latin1_General_CP1_CI_AI FROM [dbo].[fnStringToRef] ('10/2005;05/2006', ';'))Mas, pessoalmente, prefiro a primeira opção por questões de desempenho.
Abraço!!
-
Cara,
Uma vez tive problema com o Collation e resolvi usando o utilitário nesse link aqui:
http://www.mcdbabrasil.com.br/modules.php?name=News&file=article&sid=244
Ve se isso te ajuda.
Abraço,
chapolin.rio@gmail.com
-
-
Bom, vlw chapolin, mas não posso alterar o Collation...
Mas vamos la, Alexandre, é o seguinte, vou postar meu procedimento:
Code BlockFUNCTION [dbo].[fnStringToRef] (@String VARCHAR(1000), @Separador CHAR(1))
RETURNS @Referencias TABLE (IDs VARCHAR(7))
AS
BEGIN
DECLARE @Ref VARCHAR(7)
IF PATINDEX ('%' + @Separador + '%', @String) = 0
INSERT INTO @Referencias VALUES (@String)
ELSE BEGIN
WHILE PATINDEX ('%' + @Separador + '%', @String) > 0 BEGIN
INSERT INTO @Referencias VALUES (SUBSTRING (@String, 1, PATINDEX ('%' + @Separador + '%', @String) - 1))
SET @String = SUBSTRING (@String, PATINDEX ('%' + @Separador + '%', @String) + 1, LEN(@String))
END
INSERT INTO @Referencias VALUES (@String)
END
RETURN
END
Usei da seguinte maneira :
Code BlockSELECT *
FROM Gss_Atendimento
WHERE
ateReferencia IN(SELECT IDs FROM [dbo].[fnStringToRef] ('09/2006', ';'))
Deu erro do collation, ai fiz a seguinte alteração :
Code BlockSELECT *
FROM Gss_Atendimento
WHERE
ateReferencia IN(SELECT IDs COLLATE Latin1_General_CI_AI FROM [dbo].[fnStringToRef] ('09/2006', ';'))
E deu certo, porém fiquei preocupado com oq vc falou sobre desempenho e alterei minha função para :
Code BlockALTER FUNCTION [dbo].[fnStringToRef] (@String VARCHAR(1000), @Separador CHAR(1))
RETURNS @Referencias TABLE (IDs VARCHAR(7) COLLATE Latin1_General_CI_AI)
AS
BEGIN
DECLARE @Ref VARCHAR(7)
IF PATINDEX ('%' + @Separador + '%', @String) = 0
INSERT INTO @Referencias VALUES (@String)
ELSE BEGIN
WHILE PATINDEX ('%' + @Separador + '%', @String) > 0 BEGIN
INSERT INTO @Referencias VALUES (SUBSTRING (@String, 1, PATINDEX ('%' + @Separador + '%', @String) - 1))
SET @String = SUBSTRING (@String, PATINDEX ('%' + @Separador + '%', @String) + 1, LEN(@String))
END
INSERT INTO @Referencias VALUES (@String)
END
RETURN
END
e executei ela usando o comando :
Code BlockSELECT *
FROM Gss_Atendimento
WHERE
ateReferencia IN(SELECT IDs FROM [dbo].[fnStringToRef] ('09/2006', ';'))
Não deu certo...
Oq vc aconselha, deixar no select mesmo ou insisti na idéia de colocar na função? -
-
Nossa, vlw mesmo, to preso com esse negócio a mais de 1 semana, pesquisei pra kct e resolvi postar aqui.
Chapolin, Gustavo Maia Aguiar e Alexandre VM, vcs são 10 =D
Alexandre, vlw cara, eu fiz oq vc falou, tava dando erro antes pq eu meio que chutei qual era a collation da coluna ateReferencia...
Ai usei o comando q vc falou (sp_help Gss_Atendimento) e verifiquei certinho o collation, sendo ele o SQL_Latin1_General_CP850_CI_AI, portanto alterei minha função para tal collation e deu certo.
...
Ufa, acabou, finalmente, finish, the end, not be continued!!!
Vlw aew =D -
-
Alexandre,
É verdade. Aquele post é para alterar o collation do banco todo, uniformizando os collation's. Realmente não é uma prática recomendável para certos casos.
Peço desculpas aí pela dica errada..Acontece!!!
Abraço a todos,
chapolin.rio@gmail.com
-