2012-03-09 112 views
0

這是我的表,我希望我的PNRNo生成爲'PNRRES001'用於第一個條目,連續條目用'PNRRES002','PNRRES002'等。 因此,在創建表格時,我只需將該列調用到將生成PNR號碼的功能,用戶只需從前端輸入CustomerNo,客戶號碼將被更新爲PNRDetails表格。如何生成一個ID爲每個插入增量的列

CREATE TABLE PNRDetails(PNRNo AS (DBO.FuncIncPNR()) ,customerNo INT 

--FUNCTION TO GENERATE THE PNR NUMBER 
ALTER FUNCTION dbo.FuncIncPNR() 
RETURNS VARCHAR(20) 
AS 
BEGIN 
DECLARE @RR VARCHAR(20) SET @RR='PNRRESA001' 
--here i have checked if no value is there then return the first value as 'PNRRESA001' 
    IF((SELECT COUNT(*)FROM PNRDetails)=0) 
    BEGIN 
    RETURN @RR 
    END 
    ELSE 
-- if any value is there then take the last value and add 1 to it and update to the table 
    BEGIN 
    DECLARE @pnr VARCHAR(20),@S1 VARCHAR(20),@S2 INT 
    DECLARE PNRCursor CURSOR Static 
    FOR SELECT PNRNo FROM PNRDetails 
    OPEN PNRCursor 
    FETCH LAST FROM PNRNo INTO @pnr 
    SET @S1=SUBSTRING(@pnr,1,7) 
    SET @S2=RIGHT(@PNR,3) 
    SET @[email protected]+1; 
    SET @[email protected][email protected]; 

    END 
    RETURN @pnr 
END 

--Here am inserting only customerNo as 5 and the PNR should be generated by my function 
INSERT INTO PNRDetails VALUES(5) 
--it shows 1 row updated :) 
SELECT * FROM PNRDetails 
-- but when i run select command it shows 
--Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32). :(

你可以運行這個。如果你找到任何可以幫助我的東西,請幫忙。任何幫助將不勝感激... 等待您的迴應...

回答

1

如果您很樂意更改表格結構。以下將完成這項工作。

CREATE TABLE [dbo].[PNRDetails](
[autoId] [int] IDENTITY(1,1) NOT NULL, 
[prnNo] AS ('PNRRES'+right('000'+CONVERT([varchar](3),[dbo].[GetRowCount]([autoId]),(0)),(3))), 
[customerNo] [int] NOT NULL, 
CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED 
(
[autoId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,  ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

編輯:解決身份問題爲您的要求PLS創建下面的函數,並在計算列傳遞如上(編輯)中的[自動識別。

CREATE FUNCTION dbo.GetRowCount 
(
@autoId INT 
) 
RETURNS INT 
AS 
BEGIN 
DECLARE @RESULTS AS INT 
SELECT @RESULTS = COUNT(autoId) FROM PNRDetails WHERE PNRDetails.autoId<@autoId 
    RETURN @RESULTS + 1 
END 
GO 

--insert

INSERT INTO PNRDetails (customerNo) VALUES(5) 
+0

請用** PNRDetails替換** Table1 ** – Kaf 2012-03-09 13:30:57

+0

感謝您的好評,但身份的一個缺點是如果我插入任何值的表,如果任何一點我ROLLBACK,差距創建,所以我想以避免IDENTITY ... – 2012-03-10 04:06:13

+0

我已經編輯,因爲你需要。請注意,這不是持久的。即如果您在任何時候刪除一行,customerNo將隨函數返回行數而更改。如果您需要持久保存,只需在表格的設計視圖中更改即可。設計視圖>選擇customerNo列>將持久性更改爲yes。 – Kaf 2012-03-10 09:45:40

5

我建議只使用IDENTITY而不是您的ID,讓SQL Server處理每個ID號與所有它的內置保護的分配用於併發性,並將格式保留到UI ....或者,創建一個定義ID的格式化版本的computed column,如果您確實需要它在數據庫中。

你與你預期的方式運行的風險是:

  • 表現不佳
  • 併發性問題 - 如果IDS的loats正在大約在同一時間產生
6

你可以嘗試使用一個計算列和一個標識列。

create table PNRDetails 
(
    ID int identity, 
    PNRNo as 'PNRRES'+right(1000+ID, 3), 
    customerNo int 
) 
+0

感謝您的一種迴應,但1的缺點與身份是如果我插入任何值的表,如果任何點我ROLLBACK,差距創建,所以我想盡量避免身份.. – 2012-03-10 04:06:26

0

1)您可以在數據庫中使用標識列(整數)

優點:容易/無縫隙中生成的ID之間

缺點:你必須選擇插入的編號&通過程序返回/查詢 如果你要顯示它到終端用戶

2)定義一個數據庫序列

優點:易於實現/可存儲/表單之前顯示給用戶 甚至保存

CONS:間隙在之間如果某個ID一旦生成&未使用

3)。從列中選擇MAX(ID)+ 1個

優點:有用,在一個表中唯一的單用戶插入

缺點:災難性的,如果你是在多個用戶 在同一tablle被插入的環境(錯配的最大IDS)

4)使用數據庫觸發器自動增量列

優點:自動

缺點:難以調試(你必須確保它的一些 原因不休息,否則插入失敗)

+0

Downvoters請註明反對意見是什麼? – 2012-03-09 13:51:41

+1

我沒有投票給你,但你的答案中至少有兩個錯誤:使用IDENTITY不會阻止差距(點1),並且數據庫序列在SQL Server 2012之前不可用,但OP詢問了2005/2008(點2)。 – Pondlife 2012-03-09 14:28:43

+0

@Pondlife感謝您的信息。你能解釋一下,當交易回滾時,身份字段如何存在差距?另外,我忽略了使用SQL Server 2005的人。 – 2012-03-09 14:32:40

0

變化的方式觸發你的作品。這樣

CREATE FUNCTION dbo.fn_FuncIncPNR(@ID int) 
RETURNS varchar(20) 
BEGIN 
Declare @Retval varchar(20), 
     @No varchar(4) 
Select @No = convert(varchar(4), @ID) 
while Len(@No) < 4 
    Select @No = '0' + @No  

Select @Retval = 'PNRRESA' + @No 
RETURN @Retval 
END 

你會發現有些東西是一個參數字段

更改您的表中創建這個

CREATE TABLE PNRDetails(PNRNo AS (dbo.fn_ShowPNRNo(wID)), wID int IDENTITY(1,1) NOT NULL, customerNo INT) 

這應該解決您的問題

+0

感謝您的迴應,與身份證1的缺點是如果我插入任何值的表,如果任何一點我ROLLBACK,差距創建,所以我想盡量避免IDENTITY .. – 2012-03-10 04:00:55

相關問題