2014-02-20 3 views
1

Мне нужно вставить некоторые ассоциации баз данных (таблица Many-to-Many в MS-SQL Server 2008) на основе Person и языка. Мои входящие данные включают таблицу, полную людей, таблицу с полными языками, а у людей есть поле с разделителями-запятыми, которые представляют собой каждый язык, с которым они связаны.Создание ассоциаций из списка с разделителями-запятыми в SQL

Так вот что таблицы будет выглядеть

Люди

----------------------------------------------- 
ID | First Name | Last Name | Languages 
----------------------------------------------- 
1 | Paul  | Johnson | English,Spanish 
2 | Jack  | Johnson | English,Hindi 
3 | Mark  | Johnson | NULL 
----------------------------------------------- 

Язык

-------------- 
ID | Name 
-------------- 
1 | English 
2 | Spanish 
3 | Hindi 
--------------  

И мне нужно, чтобы получить его в таблицу, которая будет, в завершение, выглядят так:

PeopleLanguage

---------------------- 
PeopleID | LanguageID 
---------------------- 
1  | 1 
1  | 2 
2  | 1 
2  | 3 

Теперь, я бы как, чтобы избежать использования курсоров или во время циклов итерации по каждому врачу и выполнять операцию, но я не могу придумать, как за пределами этого (также, я не полностью понимаю курсоры: p)

Надеюсь, что SO сможет придумать хорошее решение для меня.

Спасибо!

ответ

-1

Предполагая, что структуры выше, я был в состоянии сделать это, вступив на чеке CHARINDEX так:

INSERT INTO PeopleLanguages (PeopleID, LanguageID) 
SELECT P.Id, L.Id 
FROM People P 
JOIN Language L ON CHARINDEX(L.Name, P.Languages) > 0 
+1

Это, кажется, работает правильно (я не тестировал фактическую вставку, но у меня есть выбор, показывающий правильные данные)! Обратите внимание, однако, вместо использования charindex я использовал функцию IN и пользовательскую функцию табличной оценки для разделения на запятую, которая выглядит примерно так: ... JOIN Языки ON Languages.Name IN (SELECT DISTINCT [items] AS [LanguageName] FROM [BigSplit] (People.Languages, ',')) –

+1

[Эта скрипка] (http://sqlfiddle.com/#!3/172c2/1) показывает, как эта простая проверка charindex может сломаться. –

+1

@Paul, вы должны, вероятно, опубликовать ответ, который вы отправили (включая определение BigSplit), в качестве ответа, и принять это, особенно если это то, с чем вы пошли. В настоящее время этот ответ не является очень безопасным решением. –

-1

Ой ... секунды ... Проверьте следующий рабочий код на SQL Fiddle. Подобно тому, который предложен дроу.

Wrond code deleted 

Вы также мог бы сделать некоторую пользу из this other asnwer и попытаться использовать CTE-х.

Проверка в соответствии с Aaron Bertrand comment SQL Fiddle ... Неправильно с моей стороны, необходимо включить больше тестов и проверить, что CHARINDEX ломается.

Попробуйте это решение (working code on SQL Fiddle)

SELECT tbl.personID,l.LangID 
FROM LANG l JOIN 
(SELECT P.[PersonID], 
     LTRIM(RTRIM(n.r.value('.', 'varchar(500)'))) [Language] 
FROM People AS P 
     CROSS APPLY (
     SELECT CAST('<A>' + REPLACE([Languages], ',', '</A><A>') + '</A>' AS XML) 
     )   AS S(XMLCol) 
     CROSS APPLY S.XMLCol.nodes('/A') AS n(r)) tbl ON l.Name = tbl.[Language] 

Это SO question и некоторые из его ответов дают разные подходы, в том числе той, которая используется.

Здесь у вас есть long and detailed performance analysis, как разбить строку с помощью CLR.

+1

Думайте, что вам нужно быть осторожным (например, языки могут быть «английскими», «английскими» (канадскими) »,« английскими »(английскими)», «французскими», «французскими (Канада)» и т. Д.). Может быть более безопасным для буфера с запятыми –

+0

Точно, что у меня было, а также, @AaronBertrand. Посмотрите мой комментарий на ответ drothe, который объясняет мое решение. Надеюсь, это правильно, похоже, выглядит правильно: D –

+2

@PaulZaczkowski Отлично! Затем вы должны обеспечить, чтобы ваша функция split была встроенной, а не многозадачной, или CLR, если это возможно. Некоторые сравнения здесь: http://www.sqlperformance.com/2012/07/t-sql-queries/split-strings ... вы также должны рассмотреть другой дизайн, ИМХО. Строки CSV не имеют места в базе данных. –