我可以在一张表格中制作“c0001,c0002”和供应商“s0001,s0002”等主键吗?
答案 0 :(得分:19)
数据库设计的想法是将每个数据元素分开。每个元素都有自己的数据类型,约束和规则。 c0002
不是一个字段,而是两个字段。与XXXnnn
或其他相同。这是不正确的,它将严重限制您使用数据的能力,并使用数据库功能和设施。
将其分解为两个独立的数据项:
column_1 CHAR(1)
column_2 INTEGER
然后在column_2
是的,您的主键可以是(column_1, column_2)
,因此您没有丢失c0002
对您的任何含义。
切勿将供应商和客户(无论“c”和“s”表示)放在同一张表中。如果你这样做,你将没有数据库表,你将有一个平面文件。由此引发的各种问题和局限。
这意味着,规范化数据。你最终会得到:
Person
或Organisation
的一个表格(Name, Address
...)Customer
CreditLimit
的一个表格(Supplier
...)PaymentTerms
{{1}}的一个表格({{1}} ...)当您需要添加列时,只在需要的位置执行,而不会影响平面文件的所有其他原因。效力范围仅限于变更范围。
答案 1 :(得分:8)
我的方法是:
创建一个ID INT IDENTITY
列并将其用作主键(它是唯一的,窄的,静态的 - 完美的)
如果您确实需要带有字母或其他内容的ID,请根据ID INT IDENTITY
尝试这样的事情:
CREATE TABLE dbo.Demo(ID INT IDENTITY PRIMARY KEY,
IDwithChar AS 'C' + RIGHT('000000' + CAST(ID AS VARCHAR(10)), 6) PERSISTED
)
此表格包含来自ID
的{{1}}个值,而1, 2, 3, 4........
将包含IDwithChar
等等。
有了这个,你就拥有了两全其美的优势:
桌上适当的,非常适合的主键(和聚类键),非常适合从其他表中引用
基于字符的ID,正确定义,计算,始终保持最新.....
答案 2 :(得分:3)
是的,实际上这是两个不同的问题, 1.我们是否可以将varchar列用作具有唯一值的自动增量列,例如类
中的滚动号ANS:是的,您可以使用下面的代码来解决问题,而无需指定ID和P_ID的值,
CREATE TABLE dbo.TestDemo
(ID INT IDENTITY(786,1) NOT NULL PRIMARY KEY CLUSTERED,
P_ID AS 'LFQ' + RIGHT('00000' + CAST(ID AS VARCHAR(5)), 5) PERSISTED,
Name varchar(50),
PhoneNumber varchar(50)
)
答案 3 :(得分:2)
我更喜欢人工主键。您的需求也可以作为计算列的唯一索引实现:
CREATE TABLE [dbo].[AutoInc](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Range] [varchar](50) NOT NULL,
[Descriptor] AS ([range]+CONVERT([varchar],[id],(0))) PERSISTED,
CONSTRAINT [PK_AutoInc] PRIMARY KEY ([ID] ASC)
)
GO
CREATE UNIQUE INDEX [UK_AutoInc] ON [dbo].[AutoInc]
(
[Descriptor] ASC
)
GO
答案 4 :(得分:1)
为主键分配域含义是一种方法,可以追溯到Cobol程序员和恐龙一起走遍地球的时候。这种做法在遗留库存系统中最常存在。它主要是一种消除一列或多列数据并将已消除列中的数据嵌入PK值的方法。
如果您想将客户和供应商存储在同一个表中,只需执行此操作,并使用自动增量整数PK并添加一个名为ContactType的列或类似的列,其中包含值'S'和'C'或其他。您不需要复合主键。
您始终可以在报告中连接这些列(PK和ContactType),例如C12345,S20000,(将整数转换为字符串)如果要消除列以节省空间(即在打印或显示的页面上),并且组织中的每个人都理解实体id的第一个字符所代表的约定对于ContactType代码。
此方法将利用内置于数据库引擎中的自动增量功能,简化数据层中的PK和相关代码,并使您的程序和数据库更加健壮。
答案 5 :(得分:0)
不是为客户执行'c0001,c0002'而是为一个表中的供应商执行's0001,s0002',而是按以下方式执行:
id
”的自动增量字段“int (10) unsigned
”。type
”的另一个字段“enum ('c', 's')
”(其中c = Customer,s = Supplier)。 正如“@PerformanceDBA”指出的那样,您可以为两个字段“id
”创建主键索引。 “type
”,以便使用正确的方法满足您的要求。
答案 6 :(得分:0)
首先让我们说你不能直接做。如果你试试
create table dbo.t1 (
id varchar(10) identity,
);
错误消息告诉您直接支持哪些数据类型。
Msg 2749,Level 16,State 2,Line 1 死'id'-Identitätsspaltemussvom Datentyp'int','bigint','smallint', 'tinyint'oder'小数'bzw。 '数字'mit 0 Dezimalstellen sein und darf keine NULL-Werte zulassen。
BTW:我试图在BOL或MSDN上找到此信息但失败了。
现在知道你不能直接这样做,使用计算列跟踪@marc_s提案是一个不错的选择。
答案 7 :(得分:0)
INSERT INTO Yourtable (yourvarcharID)
values('yourvarcharPrefix'+(
SELECT CAST((SELECT CAST((
SELECT Substring((
SELECT MAX(yourvarcharID) FROM [Yourtable ]),3,6)) AS int)+1)
AS VARCHAR(20))))
此处varchar
列以“RX”为前缀,然后是001
,因此我在其前缀之后选择substring
并单独增加该数字。
答案 8 :(得分:0)
我们可以使用表定义添加Default Constraint Function
来实现此目的。
首先创建表格
create table temp_so (prikey varchar(100) primary key, name varchar(100))
go
第二次创建新的User Defined Function
-
create function dbo.fn_AutoIncrementPriKey_so ()
returns varchar(100)
as
begin
declare @prikey varchar(100)
set @prikey = (select top (1) left(prikey,2) + cast(cast(stuff(prikey,1,2,'') as int)+1 as varchar(100)) from temp_so order by prikey desc)
return isnull(@prikey, 'SB3000')
end
go
要添加default constraint
的第三个更改表定义 -
alter table temp_so
add constraint df_temp_prikey
default dbo.[fn_AutoIncrementPriKey_so]() for prikey
go
第四个insert
新行没有指定primary column
的值 -
insert into temp_so (name) values ('Rohit')
go 4
立即查看表格中的数据
select * from temp_so
输出 -
prikey name
SB3000 Rohit
SB3001 Rohit
SB3002 Rohit
SB3003 Rohit
答案 9 :(得分:0)
您可以尝试以下代码:
SET @variable1 = SUBSTR((SELECT id FROM user WHERE id = (SELECT MAX(id) FROM user)), 5, 7)+1;
SET @variable2 = CONCAT("LHPL", @variable1);
INSERT INTO `user`(`id`, `name`) VALUES (@variable2,"Jeet");
答案 10 :(得分:-1)
没有。如果你真的需要这个,你必须手动生成ID。