2016-12-22 64 views
0

例として「ニュース」という表を作成したいと思います。この表では、私はgroup_idlang_idを持っています。 group_idは「ニュース」のIDはそのままですが、一部の言語では翻訳されているため、group_idとなります。このgroup_idlang_idという新しい "ニュース"を挿入しますが、lang_idの場合はすべて同じですが、挿入コマンドにアタッチするとautoIncrementとなります。
テーブルの例私は達成したいもの。
私はドイツ語(1)、英語(2)、フランス語(3)でこの新しいニュースを言うでしょうが、それは同じgroup_idを持つこのLangsの新しい行を作成します。複数回存在する主キー

表:News

x-----------------------------x 
| group_id| lang_id | news | 
x---------|-----------|-------x    
| 1 |  1  | Hallo | 
| 1 |  2  | Hello | 
| 1 |  3  | Holla | 
| 2 |  1  | bye | 
| 2 |  2  | byebye| 
| 2 |  3  | Ciao | 
x-----------------------------x 

どのように私は主キーで、group_idは主キーになることを達成できます?

+3

これはユニークではないため、できません。主キーは一意でなければなりません。 groupidとlang_idの両方を使用してキーを作成する必要があります。主キーとは、特定のキーを持つ行を要求すると、1つの行だけが返されることを意味します。 –

+0

PS 'group_id'をautoincrementに設定することはできません。なぜなら、各行に*異なる*値があるからです。 –

+1

group_id、lang_idの組み合わせがプライマリキーを形成し、シーケンスを使用してgroup_idを "auto inc"値にすることができます。より良いが、そのgroup_idが '親'テーブルにある2つのテーブルにする。 –

答えて

1

プライマリキーは、定義によって一意である必要があります。
これは、あなたのケースでは、テーブルの主キーがgroup_idlang_idの組み合わせであることを意味します。
あなたのgroup_idがID列である可能性がありますが、これは可能ですが、既存のコンテンツの新しい言語ごとにSET IDENTITY_INSERTを使用する必要があります。

例:

CREATE TABLE tblNews 
(
    group_id int identity(1,1) not null, 
    lang_id int not null, 
    news varchar(20), 
    primary key(group_id, lang_id) 
) 

INSERT INTO tblNews VALUES(1, 'hello') 

SET IDENTITY_INSERT tblNews ON 
INSERT INTO tblNews (group_id, lang_id, news) VALUES(1, 2, 'hello') 
INSERT INTO tblNews (group_id, lang_id, news) VALUES(1, 3, 'holla') 
SET IDENTITY_INSERT tblNews OFF 

INSERT INTO tblNews VALUES(1, 'good bye') 

SET IDENTITY_INSERT tblNews ON 
INSERT INTO tblNews (group_id, lang_id, news) VALUES(2, 2, 'byebye') 
INSERT INTO tblNews (group_id, lang_id, news) VALUES(2, 3, 'Ciao') 
SET IDENTITY_INSERT tblNews OFF 

SELECT * 
FROM tblNews 

結果:

group_id lang_id  news 
1   1   hello 
1   2   hello 
1   3   holla 
2   1   good bye 
2   2   byebye 
2   3   Ciao 

この設計は明らかに可能ですが、私はそれを推薦苦労しています。

tblNews 
newsId int identity(1,1) primary key, 
-- and whatever else content that is not language-dependent 

tblLanguages 
languageId int identity(1,1), 
languageName nvarchar 

tblNewsContent 
NewsId (pk) 
LanguageId (pk) 
Contant nvarchar 
+0

私は、このような問題に対する最良の解決策として正解とマークします。ベストプラクティスであるので、私は3テーブルスキーマを使います。 – AkAk47

+0

喜んで:-)。私はこれがベストプラクティスかどうかはわかりませんが、それが私が知っている最良のものです:-)。 –

0

3つのテーブル方式が最良の選択肢ですが、私は希望:言語のためのニュースのための1つのテーブル、一つのテーブルを、1台の翻訳のために - 私はおそらく、多言語データベースに異なるアプローチを使用します翻訳に依存しないユニークなものが必要だと言います。

SQL Server 2012+を使用している場合は、この状況でシーケンスを使用できますが、それがベストプラクティスであるとは言えません。

rextester:ゾハールPeledは、説明したようにhttp://rextester.com/RRTJ4439

create sequence dbo.NewsIdSequence as int start with 1 increment by 1; 

create table Lang (
    id int not null 
    , name nvarchar(64) 
    , alias nvarchar(64) 
    , constraint pk_Lang primary key clustered (id) 
    , constraint uq_Lang_Name unique (name) 
); 

create table NewsLanguage (
    news_id int not null 
    constraint df_NewsLanguage_news_id default (next value for dbo.NewsIdSequence) 
    , lang_id int not null 
    , title nvarchar(256) not null 
    , article nvarchar(max) not null 
    , constraint pk_NewsLanguage primary key clustered (news_id, lang_id) 
    , constraint fk_langLanguage_lang_id foreign key (lang_id) references lang(id) 
); 

insert into Lang (id, Name, alias) 
    select top 3 langid, name, alias 
    from syslanguages 
    order by langid; 

declare @NextNewsId int; 
set @NextNewsId = next value for dbo.NewsIdSequence; 

insert into NewsLanguage(news_id, lang_id, title, article) 
      select @NextNewsId, 0, 'Hello', 'Hello ... ' 
    union all select @NextNewsId, 1, 'Hallo', 'Hallo ... ' 
    union all select @NextNewsId, 2, 'Bonjour', 'Bonjour ...'; 

set @NextNewsId = next value for dbo.NewsIdSequence; 

insert into NewsLanguage(news_id, lang_id, title, article) values 
    (@NextNewsId, 0, 'Goodbye','Goodbye ...') 
    , (@NextNewsId, 1, 'Auf Wiedersehen', 'Auf Wiedersehen ...') 
    , (@NextNewsId, 2, 'Au Revoir', 'Au Revoir ...'); 

select * 
    from dbo.NewsLanguage nl 
    inner join dbo.Lang l on nl.lang_id = l.id 

3つの表法は、良いだろう。ハンガリー表記のないバージョンがあります:

create table Lang (
    id int not null identity (1,1) 
    , name nvarchar(64) 
    , alias nvarchar(64) 
    , constraint pk_Lang primary key clustered (id) 
    , constraint uq_Lang_Name unique (name) 
); 

create table News (
    id int not null identity (1,1) 
    , unique_column_of_importance nvarchar(64) 
    , constraint pk_News primary key clustered (id) 
    , constraint uq_News_Title unique (unique_column_of_importance) 
); 

create table NewsLanguage (
    news_id int not null 
    , lang_id int not null 
    , title nvarchar(256) not null 
    , article nvarchar(max) not null 
    , constraint pk_NewsLanguage primary key clustered (news_id, lang_id) 
    , constraint fk_NewsLanguage_news_id foreign key (news_id) references news(id) 
    , constraint fk_NewsLanguage_lang_id foreign key (lang_id) references lang(id) 
); 
関連する問題