none
Два запроса объединить в один RRS feed

  • Вопрос

  • Приветствую,

    есть таблица в БД, которая хранит различные слова и варинты перевода их на другие языки. Для каждого слова возможные варианты его перевода храняться в виде XML поля. Если нужно вытащить слов и его переводы внутри хранимой процеду используется

    два вот таких запроса:

    1. Для нужного слова вытаскиваем поле xml с вариантами перевода

    declare @xmlWord xml
    		
    		select
    			@xmlWord = vocabulary.Word
    		from
    			dbo.Vocabulary vocabulary with (nolock)
    		where
    			vocabulary.Id = @word_id

    2. Данные в XML преобразуем в таблицу и обединяем с остальными данными по слову:

    select
    			vocabulary.Id Id
    			, vocabulary.TypeId TypeId
    			, vocabulary.GroupId GroupId
    			, isnull(vocabulary_group.Name, 'Undefinite') GroupName
    			, vocabulary_type.Name TypeName
    			, vocabulary.RuTranslation RuTranslation
    			, variants_of_translation.Id WordId
    			, variants_of_translation.Value WordValue
    			, variants_of_translation.[Description] WordDescription 
    		from	
    			dbo.Vocabulary vocabulary with (nolock)
    				left join dbo.listVocabularyGroup vocabulary_group with (nolock)
    					on vocabulary_group.Id = vocabulary.GroupId
    				inner join dbo.listVocabularyType vocabulary_type with (nolock)
    					on vocabulary_type.Id = vocabulary.TypeId
    				inner join dbo.GetWordTranslationsVariants(@xmlWord) variants_of_translation
    					on vocabulary.Id = @word_id	

    GetWordTranslationsVariants -это функция возвращающая таблицу, которую она получает из XML вот так:

    create function dbo.GetWordTranslationsVariants (
    	@xmlWord xml)
    returns @t table (Id uniqueidentifier, Value nvarchar(1000), [Description] nvarchar(1000))
    as
    begin
    	declare @Id uniqueidentifier
    	declare @Value nvarchar(1000)
    	declare @Description nvarchar(1000)
    	
    	insert into @t 
    	select
    		ref.value('@Id', 'uniqueidentifier')
    		, ref.value('@Value', '[nvarchar](1000)')
    		, ref.value('@Description', '[nvarchar](1000)')
    	from
    		@xmlWord.nodes('/Word/Variant') as node(ref) 
    	
    	return
    end

    Это всё прекрасно работает, если нужно получить одно слово, но вот если разом нужно вытащить несколько слов, то сначало нужно получать xml по каждому из них, а потом само слово - т.е. циклом вытаскивать по одному слову и объединять их в результирующий набор - это совсем не айс.

    Выше представленные запросы у меня не получается объединить в один, т.к. результат любого подзапроса  - это таблица, а пользовательские функции t-sql как я понимаю не умеют принимать таблицы в качестве аргументов.

    Кто-нибудь может подсказать как два запроса выше, можно объединить в один? - так чтобы за раз можно было ватащить несколько слов с переводами.  


    • Изменено A.G.Sedov 29 февраля 2012 г. 9:41
    29 февраля 2012 г. 8:53

Ответы

  • Изложено несколько путано, но, судя по всему, как раз для вас придумали apply

    select v.Word, t.*
    
    from Vocabulary v
    
    cross apply GetWordTranslationsVariants(v.Word) t
    
    where v.Id in ( @id1, @id2, @id3) -- ваше условие отбора слов

    PS. Почитайте про with(nolock) и не используйте его.

    • Помечено в качестве ответа A.G.Sedov 29 февраля 2012 г. 13:41
    29 февраля 2012 г. 13:15

Все ответы

  • Изложено несколько путано, но, судя по всему, как раз для вас придумали apply

    select v.Word, t.*
    
    from Vocabulary v
    
    cross apply GetWordTranslationsVariants(v.Word) t
    
    where v.Id in ( @id1, @id2, @id3) -- ваше условие отбора слов

    PS. Почитайте про with(nolock) и не используйте его.

    • Помечено в качестве ответа A.G.Sedov 29 февраля 2012 г. 13:41
    29 февраля 2012 г. 13:15
  • 1) Спасибо, помогло.

    2) что страшного в with (nolock), кроме того, что пользователь может получить не закомитченные данные?

    29 февраля 2012 г. 13:41
  • 2) что страшного в with (nolock), кроме того, что пользователь может получить не закомитченные данные?


    Есть шанс прочитать одну запись несколько раз или не дочитать чего-то, но вы от этого не застрахованы и при уровне изоляции read committed

    http://www.t-sql.ru

    29 февраля 2012 г. 13:50
    Модератор
  • У вас неправильное отношение к хинтам. Хинтов следует избегать и пользоваться ими исключительно в случаях крайней необходимости, отдавая себе отчёт в том, что и зачем вы делаете. Какую проблему вы решаете при помощи чтения в read uncommitted? Никогда не надо такие вещи просто так писать.
    • Изменено Roman Sergeev 29 февраля 2012 г. 15:29
    29 февраля 2012 г. 15:28