多次存在的主键

时间:2016-12-22 13:17:54

标签: sql sql-server primary-key

我想创建一个表"新闻"作为例子。在此表中,我有一个group_id和一个lang_idgroup_id保留"新闻"的ID但是group_id因为它在某些语言中有翻译。如果我插入新的"新闻" group_idautoIncrement将为lang_id使用不同的lang_id但对于我附加到插入命令的每个group_id都是相同的 例如,我希望实现的目标 我在这里说新的德语新闻(1),英语(2),法语(3)它将为这个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

如何使用主键实现这一点,lstValues.add(total.getString("uname")+","+total.getString("loginname")+","+total.getString("uadd")); 将成为主键?

2 个答案:

答案 0 :(得分:1)

根据定义,主键必须是唯一的 这意味着,在您的情况下,表格的主键应该是group_idlang_id的组合。
至于你的group_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

答案 1 :(得分:0)

三种表方法是最佳选择,但我认为它需要一些不依赖于翻译的独特方法。

如果您使用的是sql server 2012+,则可以使用序列来解决这种情况,但我不能说这是最佳做法。

rextester: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

Zohar Peled解释说,这三种方法会更好。这是一个没有匈牙利符号的版本:

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)
  );