Запятая Разграниченная строковая Потребность SQL к разделенному

У меня есть эта строка, которую я получаю из приложения A .NET, B, C, D, E, F,

Я хотел записать оператор выбора sql как

set @string = 'A,B,C,D,E,F'

select * from tbl_test 
where tbl_test.code in (@string)

Эта работа привычки в T-SQL, потому что это использует @string как одна строка это не разделяет значения. Есть ли какие-либо способы, которыми я могу сделать это?

5
задан Tom H 29 June 2010 в 18:33
поделиться

9 ответов

Думаю, самым простым способом сделать это будет динамическая генерация SQL:

// assuming select is a SqlCommand
string[] values = "A,B,C,D,E,F".Split(',');
StringBuilder query = new StringBuilder();
query.Append("select * from tbl_test where tbl_test.code in (");
int i = 0;
foreach (string value in values) {
    string paramName = "@p" + i++;
    query.Append(paramName);
    select.Parameters.AddWithValue(paramName, value);
}
query.Append(")");
select.CommandText = query.ToString();

// and then execute the select Command
1
ответ дан 13 December 2019 в 22:06
поделиться
# create an array with FALSE and lines from the file
unset list
while read -r line
do
    list+=("FALSE")
    list+=("$line")
done < data_file

# set some entries to TRUE
for entry in 0 2 5 11 12 19
do
    list[entry]="TRUE"
done

# display the dialog
ans=$(zenity --list --text "Show List" --checklist --column "Pick" --column "List" "${list[@]}" --separator=":")
echo $ans    
-121--1948912-

Для получения DPI можно использовать следующую функцию javascript.

<script type="text/javascript">
   var dpi = {
      v: 0,
      get: function (noCache) {
         if (noCache || dpi.v == 0) {
            e = document.body.appendChild(document.createElement('DIV'));
            e.style.width = '1in';
            e.style.padding = '0';
            dpi.v = e.offsetWidth;
            e.parentNode.removeChild(e);
         }
         return dpi.v;
      }
   }

    alert(dpi.get(true));  // recalculate
    alert(dpi.get(false)); // use cached value
</script>

Однако я думаю, что он всегда будет возвращать 96 на оконных машинах.

Насколько мне известно, операционная система не имеет пути определять фактические физические размеры видового экрана. Таким образом, вполне может быть, что программное обеспечение на самом деле не может знать реального DPI.

Однако профессионалы в определенных областях проверяют соответствие DPI на экране реальному DPI. В этом случае вышеуказанного javascript, вероятно, будет достаточно.

Примечание:
Протестировал вышеуказанный код в Opera 9, IE6 & 7 и Firefox 3,6 на WinXP и Win2k.

Update:
Добавлен параметр noCache. Но я сомневаюсь, что это даст какой-то эффект. Я протестировал его с помощью zoom в FireFox и Opera на вышеупомянутых версиях окон, и они продолжают цитировать DPI как '96', независимо от величины zoom. Интересно было бы посмотреть, что из этого делают мобильные устройства.

-121--3926367-

Предложение dynamic IN означает:

  1. Преобразование списка, разделенного запятыми, во временную таблицу для соединения с
  2. Использование динамического SQL (EXEC или EXEC sp_executesql)

Динамический пример SQL


DECLARE @SQL NVARCHAR(4000)

    SET @SQL = 'SELECT * FROM tbl_test t
                 WHERE t.code IN (@string_param)

BEGIN

  EXEC sp_executesql @SQL N'@string_param VARCHAR(100)', @string

END

. Имейте в виду, что sp _ executesql имеет значение 2005 +, и является предпочтительным, так как будет кэшировать план запроса. Дополнительные сведения см. в разделе Проклятие и благословения динамического SQL , но помните о атаках впрыска SQL .

1
ответ дан 13 December 2019 в 22:06
поделиться

Создайте функцию, определяемую пользователем, которая принимает строку на вход и возвращает таблицу:

create function [dbo].[f_SplitString] (@str as varchar (1000))
returns @t table (value varchar (50))
etc...

Затем настройте оператор Select:

select * from tbl_test 
where tbl_test.code in (select value from f_SplitString(@string))
1
ответ дан 13 December 2019 в 22:06
поделиться

Вот функция, которая возвращает строку с разделителями в виде набора строк

set @string = 'A,B,C,D,E,F'      

select * from tbl_test       
where tbl_test.code in (select r from ftDelimitedAsTable(',',@string )    


  --/*----------------------------------------------------------------
    Create     FUNCTION [dbo].[ftDelimitedAsTable](@dlm char, @string varchar(8000))
    RETURNS 
    --------------------------------------------------------------------------*/
    /*------------------------------------------------------------------------
    declare @dlm  char, @string varchar(1000)
    set @dlm=','; set @string='t1,t2,t3';
    -- tHIS FUNCION RETUNRS IN THE ASCENDING ORDER
    -- 19TH Apr 06
    ------------------------------------------------------------------------*/
    --declare
        @table_var TABLE 
        (id int identity(1,1),
            r varchar(1000) 
         )
    AS
    BEGIN
    -- a.p --
    --Modified  18th Nov. 04

        declare @n int,@i int
        set @n=dbo.fnCountChars(@dlm,@string)+1
        SET @I =1
        while @I <= @N
            begin

                --print '@i='+convert(varchar,@i)+ ' AND INSERTING'
                insert @table_var
                    select dbo.fsDelimitedString(@dlm,@string,@i)
                set @I= @I+1

            end
    --PRINT '*************** ALL DONE'
        if @n =1 insert @TABLE_VAR VALUES(@STRING)
    --select * from @table_var
        delete  from @table_var where r=''
        return
    END


USE [QuickPickDBStaging]
GO
/****** Object:  UserDefinedFunction [dbo].[fsDelimitedString]    Script Date: 02/22/2010 12:31:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

Create function [dbo].[fsDelimitedString](
            @DelimiterStr varchar(100)
            ,@str varchar(4000)
            ,@pos int=1)
 returns varchar(4000)
as
/*
AP -- Dec 2003
Declare @DelimiterStr varchar(4000),@str varchar(4000) ,@pos int
set @delimiterStr = '-'
set @pos=10
set @str ='wd-1-22-333-4444-55555-666666-q-9'
*/
Begin
declare @rx varchar(4000)
set @rx=''; set @pos=@pos-1
IF DBO.fnCountChars(@DelimiterStr,@str) > 0 
    Begin
        if dbo.fnCountChars(@delimiterStr,@str) < @pos
        begin
            set @rx= null
            goto nulls
        end
        declare @i1 int,@tPos int,@ix int

        set @ix=1
        set @tPos=0
        while @tpos <> @pos
        Begin
            set @ix=charindex(@DelimiterStr,@str,@ix+1)
            if @ix > 0 set @tpos=@tpos+1
        end
        set @i1= charindex(@DelimiterStr,@str,@ix+1)
        if @i1=0 
                set @rx=substring(@str,@ix+1,len(@str)-@ix)
        else
            begin
                if @ix=1  
                    set @rx=substring(@str,@ix,@i1-@ix)
                else
                    set @rx= substring(@str,    @ix+1,@i1-@ix-1)        
            end
    --  'print 'ix='+convert(varchar,@ix)+' @i1='+convert(varchar,@i1)+' @rx='+@rx
        RETURN @RX
    end
nulls:  
    RETURN  @rx
end
1
ответ дан 13 December 2019 в 22:06
поделиться

У вас есть несколько вариантов:

  • Если вы не против, просто составляйте SQL-оператор динамически перед вызовом SQL. Существует ограничение на количество значений в операторе IN
  • Используйте Table-valued UDF, который разделяет строку и возвращает таблицу. Тогда ваш запрос будет использовать либо IN, либо лучше просто JOIN оператор (среди других реализаций я предпочитаю SQL User Defined Function to Parse a Delimited String).

Ваш код будет выглядеть так:

select     tbl_test.*
from       tbl_test 
inner join fn_ParseText2Table(@string) x
       on  tbl_test.code = x.txt_value 
  • Поскольку вы используете SQL Server 2005, вы можете написать CLR Table-valued UDF, которая будет выполнять ту же работу, что и предыдущая UDF, но будет намного меньше и быстрее, поскольку операции со строками в CLR обрабатываются намного лучше, чем в SQL.
1
ответ дан 13 December 2019 в 22:06
поделиться

Вы можете упростить задачу с помощью встроенных функций sql:

set @string = 'A,B,C,D,E,F'

select * from tbl_test 
where CHARINDEX(ISNULL(tbl_test.code, 'X'), @string) > 0

PATINDEX можно использовать, если вам нужно более одного символа.

1
ответ дан 13 December 2019 в 22:06
поделиться

Ничего простого. Вы можете написать функцию, которая будет принимать этот список и разделять его на таблицу, которую вы можете запросить в операторе IN ().

0
ответ дан 13 December 2019 в 22:06
поделиться

3 варианта

  1. Используйте регулярное выражение для замены "," на "','", чтобы оно стало правильным ('A', 'B' ...) list
  2. Преобразуйте список в XML, а затем проанализируйте XML в вашем SELECT
  3. Напишите функцию SPLIT для преобразования списков с разделителями-запятыми в таблицы
2
ответ дан 13 December 2019 в 22:06
поделиться

Очень часто задаваемый вопрос! Вам нужна функция с табличным значением.

Но не изобретайте велосипед, написав свое собственное, я нашел десятки только с помощью Googling sql split . Вот один от Microsoft:

http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=StringArrayInput

Я использовал для этого динамический SQL, но это означало, что мне пришлось копать код и копируйте его в каждое новое приложение. Теперь мне даже не нужно об этом думать.

2
ответ дан 13 December 2019 в 22:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: