2016-04-12 22 views
1

benim dilli programında, böyle, dil dosyası oluşturma sırasında bir dil veritabanından dil dizeleri getir:alın dil dizeleri yinelemeli

SELECT [key], translation FROM language WHERE [email protected] 
UNION 
SELECT [key],translation FROM language WHERE lang='EN' 
AND [key] NOT IN(SELECT [key] FROM language WHERE [email protected]) 

Gördüğünüz gibi, İngilizce tüm diller için son çare olduğunu, should Eksik çeviri dizeleriyle karşılaşıyoruz.

tablo düzenidir:

[lang] VARCHAR(5) 
[key] VARCHAR(100) 
[translation] VARCHAR(MAX) 

Şimdi "İngilizce" hariç her dil tanımlanmış bir yedek dil olan bir dil ağacı, olması mantıklıdır. Böyle bir şey:

English 
|- English (UK) 
|- German 
| |- German (Switzerland) 
| |- German (Austria) 
|- French 
| |- French (Canada) 
| |- Italian 
| |- Portuguese 
| | |- Portuguese (Brazil) 
|- Russian 
| |- Czech 

Bu şekilde, dil dizeleri (henüz) İtalyanca mevcut şimdilik Fransızcadan dil dizeleri ile değiştirilebilir değil, İngilizce daha İtalyan kullanıcılara daha okunaklı olabilir [kaynak belirtilmeli. Ayrıca, Almanca (İsviçre) sadece Almanca'dan gerçekten farklı olan dizeleri içermeli ve tüm dizilerin tam bir kopyası olmak zorunda kalmayacaktır.

Ancak dil dizelerini veritabanından getirirken, bunu nasıl yaparım?

Ben https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx anlamaya çalıştık, ancak kısıtlamayı resursive parçası haline "sadece sonuç kümesinin henüz parçası olan anahtarları getir" nasıl ekleneceğini ben alamadım:

WITH MyCTE ([key], translation) 
AS 
(
    SELECT [key],translation FROM language l1 
    WHERE lang = @lang 
    UNION ALL 
    SELECT [key],translation FROM language l2 
    WHERE lang = (SELECT translation FROM language l3 WHERE lang = @lang AND [key] = 'PARENTLANGUAGE') 
    AND [key] NOT IN l1 
) 
SELECT * 
FROM MyCTE 

Örneği Tablo DDT:

CREATE TABLE language(
    lang VARCHAR(5) NOT NULL, 
    [key] VARCHAR(100) NOT NULL, 
    [translation] VARCHAR(MAX) NOT NULL 
) 

Örnek Veri:için

INSERT INTO language([lang],[key],[translation]) ('EN','YES','Yes'); 
INSERT INTO language([lang],[key],[translation]) ('EN','NO','No'); 
INSERT INTO language([lang],[key],[translation]) ('EN','OK','OK'); 
INSERT INTO language([lang],[key],[translation]) ('EN-US','NO','Nope'); 
INSERT INTO language([lang],[key],[translation]) ('DE','YES','Ja'); 
INSERT INTO language([lang],[key],[translation]) ('DE','NO','Nein'); 
INSERT INTO language([lang],[key],[translation]) ('EN','JANUARY','January'); 
INSERT INTO language([lang],[key],[translation]) ('DE','JANUARY','Januar'); 
INSERT INTO language([lang],[key],[translation]) ('DE-AT','JANUARY','Jänner'); 
INSERT INTO language([lang],[key],[translation]) ('EN-US','PARENTLANGUAGE','EN'); 
INSERT INTO language([lang],[key],[translation]) ('DE','PARENTLANGUAGE','EN'); 
INSERT INTO language([lang],[key],[translation]) ('DE-AT','PARENTLANGUAGE','DE'); 

Beklenen sonuç:

[key] translation 
------------------- 
YES  Ja 
NO  Nein 
OK  OK 
JANUARY Jänner 
+0

Lütfen örnek veriniz http://sqlfiddle.com – lad2025

+0

Çocuk diliniz ebeveyninizle nasıl ilişkilendirilir? –

+0

@ AllanS.Hansen Şu an itibariyle bağlantı yok. Bunun için bir çeviri dizesi ('[key] = 'PARENTLANGUAGE' ') kullanmayı planlıyorum, ancak diğer öneriler için açıktayım. – Alexander

cevap

1

İşte olası bir seçenek. Devam edip bunun kesinlikle bunu yapmanın en şık yolu olmadığını söyleyeceğim.

CREATE TABLE dbo.Languages 
(
    lang varchar(5) not null CONSTRAINT PK_Languages PRIMARY KEY CLUSTERED, 
    langparen varchar(5) null CONSTRAINT FK_Languages_Parent FOREIGN KEY REFERENCES dbo.Languages(lang) 
); 

CREATE TABLE dbo.Translations 
(
    translation_id int not null identity(1,1), 
    [key] varchar(100) not null, 
    lang varchar(5) not null constraint FK_Translations_Languages FOREIGN KEY REFERENCES dbo.Languages(lang), 
    translation varchar(MAX) not null, 
    CONSTRAINT PK_Translations PRIMARY KEY NONCLUSTERED([key],lang) 
) 

CREATE CLUSTERED INDEX CX_Translations ON dbo.Translations (translation_id); 
GO 

INSERT INTO dbo.Languages 
(lang, langparen) 
SELECT 'EN', NULL 
UNION ALL 
SELECT 'EN-US', 'EN' 
UNION ALL 
SELECT 'DE', 'EN' 
UNION ALL 
SELECT 'DE-AT', 'DE'; 

INSERT INTO dbo.Translations([lang],[key],[translation]) VALUES('EN','YES','Yes'); 
INSERT INTO dbo.Translations([lang],[key],[translation]) VALUES('EN','NO','No'); 
INSERT INTO dbo.Translations([lang],[key],[translation]) VALUES('EN','OK','OK'); 
INSERT INTO dbo.Translations([lang],[key],[translation]) VALUES('EN-US','NO','Nope'); 
INSERT INTO dbo.Translations([lang],[key],[translation]) VALUES('DE','YES','Ja'); 
INSERT INTO dbo.Translations([lang],[key],[translation]) VALUES('DE','NO','Nein'); 
INSERT INTO dbo.Translations([lang],[key],[translation]) VALUES('EN','JANUARY','January'); 
INSERT INTO dbo.Translations([lang],[key],[translation]) VALUES('DE','JANUARY','Januar'); 
INSERT INTO dbo.Translations([lang],[key],[translation]) VALUES('DE-AT','JANUARY','Jänner'); 

go 


with recurse as 
(
    select lang, langparen, lvl = 0, list = cast(lang as varchar(8000)) from dbo.Languages where langparen IS NULL 
    UNION ALL 
    select lang.lang, lang.langparen, paren.lvl + 1, list = cast(paren.list + ',' + lang.lang as varchar(8000)) 
    FROM dbo.Languages lang 
    JOIN recurse paren ON paren.lang = lang.langparen 
) 
select * into #recurse from recurse 

declare @lang varchar(100) = 'DE-AT'; 

declare @langstring varchar(8000); 

select @langstring = list from #recurse where lang = @lang 

;WITH lists AS 
(
SELECT t.*, rid = ROW_NUMBER() OVER (PARTITION BY t.[key] order by lvl desc) 
FROM dbo.Translations t 
join #recurse r ON t.lang = r.lang 
join dbo.split (@langstring, ',') s on s.Item = t.lang 
) 

SELECT * FROM lists where rid = 1 

kilit noktaları bazıları

: Ben ağaç için bir hiyerarşi inşa diye
  1. ben gibi, belirli bir dil ve onun en yakın ebeveyne de vardı ayrı diller masasına Yukarıda bahsettin. Çeviri tablosunu "Translations" olarak aradım.

  2. Ağacın "yolunu" da, yukarıdan aşağı doğru birleştiren özyinelemeli bir sorgu yazdım. Bu, hierarchy veri türünü kullanarak kesinlikle daha zarif bir şekilde yapılabilirdi, ancak bu yolu daha az becerikli buluyorum.

  3. Ana sorgu için, hem yinelemeli sonuçları hem de en yüksek düzeydeki dizeyi (bu durumda "De-At") çekiyorum. Yinelemeli sonuçlar, yinelemenizin en yüksek "seviyesinde" başlayan bir ROW_NUMBER aramasına izin verir ve mevcut her bir anahtar için aşağı inin.