'আইডি' বিন্যাসটি সহ: YYYYNNNNNN NNNNNN অংশটি প্রতি বছর পুনরায় আরম্ভ করবে


11

আমার ব্যবসায়ের প্রয়োজনীয়তা রয়েছে যে ইনভয়েস টেবিলের প্রতিটি রেকর্ডে একটি আইডি রয়েছে যা YYYYNNNNN এর মতো দেখাচ্ছে।

এনএনএনএনএনএন অংশটি প্রতি বছরের শুরুতে পুনরায় চালু করা দরকার। সুতরাং ২০১ 2016 সালে প্রবেশ করা প্রথম সারিটি 2016000001 এবং দ্বিতীয়টি 2016000002 এর মতো দেখাবে Le

প্রাথমিক কী হতে আমার এই আইডিটির দরকার নেই এবং আমি তৈরির তারিখটিও সংরক্ষণ করি। ধারণাটি হ'ল এই 'ডিসপ্লে আইডি'টি অনন্য (তাই আমি এটি দিয়ে জিজ্ঞাসা করতে পারি) এবং মানব গোষ্ঠী দ্বারা সক্ষম, বছর বছর ধরে।

কোনও রেকর্ড মুছে ফেলা সম্ভব নয়; তবে, আমি এই জাতীয় কিছুটির বিরুদ্ধে ডিফেন্সিভালি কোড করতে চাইছি।

প্রতিবছর একটি নতুন সারি aোকানোর জন্য এই বছর সর্বাধিক আইডির জন্য জিজ্ঞাসা না করে আমি কীভাবে এই আইডি তৈরি করতে পারি?

ধারনা:

  • CreateNewInvoiceSP, যা MAXসেই বছরের জন্য মূল্য পায় (ইয়াকি)
  • কিছু সঠিকভাবে এটি করার জন্য বৈশিষ্ট্যে অন্তর্নির্মিত যাদুকরী (আমি সঠিক স্বপ্ন দেখতে পারি)
  • কিছু ইউডিএফ বা কিছু নির্দিষ্ট করতে সক্ষম হচ্ছে IDENTITYবা DEFAULTঘোষণা (??)
  • একটি দৃশ্য যা ব্যবহার করে PARTITION OVER + ROW()(মুছে ফেলা সমস্যাযুক্ত হবে)
  • একটি ট্রিগার চালু INSERT(এখনও কিছু MAXজিজ্ঞাসা চালানো দরকার :()
  • একটি বার্ষিক পটভূমি কাজ, প্রতিটি বছরের জন্য MAX সহ একটি টেবিল আপডেট করে যা আমি তখন ... কিছু না ?!

যার সব কিছুটা অ-আদর্শ। কোনও ধারণা বা প্রকরণ যদিও স্বাগত!


আপনার কয়েকটি ভাল উত্তর রয়েছে তবে আপনি যদি পিকে হিসাবে বছর, আইডি থাকেন তবে সর্বোচ্চটি নির্বাচন করুন বেশ দ্রুত।
পাপারাজ্জো

একটি নির্বাচন করুন সর্বোচ্চ আইডি ক্যোয়ারী ব্যবহার করা একটি সাধারণ অনুশীলন। যে ব্যবহার।
উউর গামহান

উত্তর:


17

আপনার ক্ষেত্রে 2 টি উপাদান রয়েছে

  • বছর
  • একটি স্বতঃবৃদ্ধি নম্বর

তাদের এক ক্ষেত্র হিসাবে সংরক্ষণ করার দরকার নেই

উদাহরণ:

  • একটি বছরের কলাম যার ডিফল্ট থাকে YEAR(GETDATE())
  • একটি ক্রমের উপর ভিত্তি করে একটি সংখ্যা কলাম।

তারপরে তাদের (যথাযথ ফর্ম্যাটিং সহ) সম্মতিযুক্ত একটি গণিত কলাম তৈরি করুন। ক্রমটি বছরের পরিবর্তে পুনরায় সেট করা যেতে পারে।

এসকিউএলফিডেলে নমুনা কোড : * (এসকিউএলফিডাল সবসময় কাজ করে না)

-- Create a sequence
CREATE SEQUENCE CountBy1
    START WITH 1
    INCREMENT BY 1 ;

-- Create a table
CREATE TABLE Orders
    (Yearly int NOT NULL DEFAULT (YEAR(GETDATE())),
    OrderID int NOT NULL DEFAULT (NEXT VALUE FOR CountBy1),
    Name varchar(20) NOT NULL,
    Qty int NOT NULL,
    -- computed column
    BusinessOrderID AS RIGHT('000' + CAST(Yearly AS VARCHAR(4)), 4)
                     + RIGHT('00000' + CAST(OrderID AS VARCHAR(6)), 6),
    PRIMARY KEY (Yearly, OrderID)
    ) ;


-- Insert two records for 2015
INSERT INTO Orders (Yearly, Name, Qty)
    VALUES
     (2015, 'Tire', 7),
     (2015, 'Seat', 8) ;


-- Restart the sequence (Add this also to an annual recurring 'Server Agent' Job)
ALTER SEQUENCE CountBy1
    RESTART WITH 1 ;

-- Insert three records, this year.
INSERT INTO Orders (Name, Qty)
    VALUES
     ('Tire', 2),
     ('Seat', 1),
     ('Brake', 1) ;

1
প্রতি বছর এটির ক্রম থাকতে পারে এটি পরিষ্কার। নিয়মিত অপারেশনের অংশ হিসাবে এইভাবে ডিডিএল চালানোর দরকার নেই।
usr ডিরেক্টরির

@gbn সুতরাং আমি কি SEQUENCE প্রতি বছরের শুরুতে পুনরায় চালু করার জন্য আমার পটভূমির কাজ দরকার ?
ডারসি থমাস

@ ওসরের দুঃখের বিষয় আপনি NEXT VALUE FORকোনও CASEবিবৃতিতে ব্যবহার করতে পারবেন না (আমি চেষ্টা করেছি)
ডারসি থমাস

8

আপনি কি বীজ = 2016000000 দিয়ে একটি পরিচয় ক্ষেত্র তৈরি করতে বিবেচনা করেছেন?

 create table Table1 (
   id bigint identity(2016000000,1),
   field1 varchar(20)...
)

এই বীজটি প্রতিবছর স্বায়ত্তশাসিত হওয়া উচিত, উদাহরণস্বরূপ 2017/1/1 রাতে আপনার সময়সূচী করা দরকার

DBCC CHECKIDENT (Table1, RESEED, 2017000000)

তবে আমি ইতিমধ্যে ডিজাইনে সমস্যাগুলি দেখতে পাচ্ছি, উদাহরণস্বরূপ: আপনার যদি মিলিয়ন রেকর্ড থাকে?


2
আর একটি সমস্যা হ'ল যদি রেকর্ডগুলি কালানুক্রমিকভাবে উপস্থিত না হয়। পরিচয়টি সম্ভবত যদি এমন হয় তবে উপায় হয় না।
ড্যানিয়েল হুটমাচার

@ লিয়াটানস্কি আমার ক্ষেত্রে আমাকে বলা হয়েছে প্রতি বছর কেবলমাত্র 50 কে রেকর্ড হওয়া উচিত। তবে এটি 1kk সারি দিয়ে নষ্ট হওয়া সম্পর্কে আপনার অর্থটি আমি পেয়েছি
DarcyThomas

1

আমি এই দৃশ্যে যা করেছি তা হ'ল বছরকে 10 ^ 6 দিয়ে গুণ করা এবং ক্রমের মান যুক্ত করা। এটির (ছোট) চলমান ওভারহেডের সাথে একটি গণিত ক্ষেত্রের প্রয়োজন না হওয়ার সুবিধা রয়েছে এবং ক্ষেত্রটি একটি হিসাবে ব্যবহৃত হতে পারে PRIMARY KEY

দুটি সম্ভাব্য গোটাচা রয়েছে:

  • নিশ্চিত করুন যে আপনার গুণকটি যথেষ্ট পরিমাণে বড় যাতে কখনই ক্লান্ত হয় না এবং

  • সিকোয়েন্সের ক্যাচিংয়ের কারণে ফাঁক ছাড়াই আপনার কোনও ক্রমের গ্যারান্টি নেই।

আমি এসকিউএল সার্ভারে বিশেষজ্ঞ নই, তবে আপনার ক্রমটি শূন্যে পুনরায় সেট করতে আপনি সম্ভবত 201x 00:00:00 এ ট্রিগার করতে একটি ইভেন্ট সেট করতে পারেন। ফায়ারবার্ডেও আমি এটি করেছি (নাকি এটি ইন্টারবাস ছিল?)।


1

সম্পাদনা করুন: এই সমাধানটি লোডের নিচে কাজ করে না

আমি ট্রিগারগুলির অনুরাগী নই, তবে আমার পক্ষে কাজ করা ভাল best

পেশাদাররা:

  • কোনও পটভূমি কাজ নেই
  • ডিসপ্লেআইডিতে দ্রুত অনুসন্ধান করতে পারে
  • ট্রিগারটির আগের এনএনএনএনএনএন অংশের জন্য স্ক্যান করার দরকার নেই
  • প্রতি বছর এনএনএনএনএন অংশ পুনরায় চালু করবে
  • প্রতি বছর 100000 সারি বেশি হলে কাজ করবে
  • ভবিষ্যতে কাজ চালিয়ে যাওয়ার জন্য স্কিমা আপডেটের (যেমন, সিকোয়েন্স রিসেট) প্রয়োজন হয় না

সম্পাদনা: কনস:

  • লোডের অধীনে ব্যর্থ হবে (অঙ্কন বোর্ডে ফিরে)

(আমি তাদের উত্তর থেকে কিছু অনুপ্রেরণা গ্রহণ করার সাথে সাথে @gbn এর ক্রেডিট) (যে কোনও ফিড ফিরে আসে এবং সুস্পষ্ট ভুলগুলি নির্দেশ করে স্বাগত জানায় :)

কিছু নতুন COLUMNএস এবং একটি যুক্ত করুনINDEX

ALTER TABLE dbo.Invoices
ADD     [NNNNNNId]      INT  NULL 

ALTER TABLE dbo.Invoices
ADD [Year]              int NOT NULL DEFAULT (YEAR(GETDATE()))

ALTER TABLE dbo.Invoices
ADD [DisplayId]     AS  'INV' +
                        CAST([Year] AS VARCHAR(4))+
                        RIGHT('00000' + CAST([NNNNNNId] AS VARCHAR(4)),  IIF (5  >= LEN([NNNNNNId]), 5, LEN([NNNNNNId])) )                  

EXEC('CREATE NONCLUSTERED INDEX IX_Invoices_DisplayId
ON dbo.Invoices (DisplayId)')

নতুন যুক্ত করুন TRIGGER

CREATE TRIGGER Invoices_DisplayId
ON dbo.Invoices
  AFTER  INSERT
AS 
BEGIN

SET NOCOUNT ON;    

UPDATE dbo.Invoices
SET NNNNNNId = CalcDisplayId
FROM (SELECT I.ID, IIF (Previous.Year = I.Year , (ISNULL(Previous.NNNNNNId,0) + 1), 1) AS CalcDisplayId  FROM
        (SELECT 
            ID  
           ,NNNNNNId 
           ,[year]
        FROM  dbo.Invoices
        ) AS Previous
    JOIN inserted AS I 
    ON Previous.Id = (I.Id -1) 
    ) X
WHERE 
   X.Id = dbo.Invoices.ID       
END
GO

আমি অত্যন্ত না এটি সুপারিশ। আপনি একবারে হালকা বোঝা নেওয়ার পরে এটি অচলাবস্থা তৈরি করতে এবং ব্যর্থতা সন্নিবেশ করতে পারে। আপনি কি একটি ডামি ডাটাবেসে একটি অনুলিপি রেখেছেন এবং কয়েক ডজন থ্রেড দিয়ে একবারে সন্নিবেশগুলি (এবং সম্ভবত নির্বাচিত / আপডেট / মুছে ফেলা) কী হবে তা দেখার জন্য এটি দিয়ে গেছেন?
কোডি কোনিয়র

@ কোডিওনিয়ার এটি মৌলিকভাবে ত্রুটিযুক্ত বা কিছুটা বিচারিক লক দিয়ে পুনরুত্থিত হতে পারে? না হলে কীভাবে সমস্যাটির কাছে যাবেন?
ডারসি থমাস

হুম। 10 টি সুতোর সাহায্যে দৌড়ে গেল। এটি মৃত লকগুলি কিনা তা নিশ্চিত নয় তবে আমি কিছু রেসের শর্ত পেয়েছি। যেখানে পূর্ববর্তী সারিগুলির ট্রিগার শেষ হওয়ার আগে একটি ট্রিগার সম্পূর্ণ হয়। এটি NULLমানগুলির একটি গুচ্ছকে প্রবেশ করার দিকে পরিচালিত করে । অঙ্কন বোর্ড ফিরে ...
DarcyThomas

তখন বিপর্যয় এড়ানো যায় :-) আমার গোপন বিষয় হল আমি প্রায় পাঁচ বছর আগে যা কিছু করেছি তার জন্য প্যাটার্নটি স্বীকৃত করেছি। আমি কেবল জানি যে আপনি পরবর্তী সিকোয়েন্সটি সন্ধানের জন্য ট্রিগের অভ্যন্তরে টেবিলটি স্ক্যান করে লোডের নিচে জিনিসগুলি ট্রিপ করে। আমি কীভাবে সমাধান করেছি তা মনে নেই তবে আমি পরে তা পরীক্ষা করে দেখতে পারি।
কোডি কোনিয়র

@ কোডিওনিয়ার আমি মনে করি না এটি স্ক্যান করছে ( ON Previous.Id = (I.Id -1) কেবল সন্ধান করা উচিত), তবে হ্যাঁ এখনও এটি কাজ করে না। যদি আমি সন্নিবেশ এবং ট্রিগার চলাকালীন টেবিলটি (?) লক করতে পারি তবে আমার মনে হয় এটি কার্যকর হবে। তবে এটি একটি কোড গন্ধের মতো শোনাচ্ছে।
ডারসি থমাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.