Create automatic code - sql

I want to create automatic code example:
B001, B002, B003, B004 .....
I have create the function for that:
CREATE FUNCTION AUTO_CODE()
RETURNS CHAR (4)
AS
BEGIN
DECLARE #KODE CHAR(4)
SELECT #KODE = COUNT (KODE_BARANG)FROM BARANG
IF #KODE>0
BEGIN
SELECT #KODE = RIGHT(KODE_BARANG,4) FROM BARANG
SET #KODE = #KODE+1
END
ELSE SET #KODE=1
RETURN 'B' + LEFT('00',3-LEN(#KODE))+(#KODE)
END
The function above only works for B001 through B010, beyond that it was back to B001. It won't work for B011, B012 or B120.
After that I have try to do with if else:
...
DECLARE KODENYA CHAR (5)
IF #KODE >= 0 AND #KODE <=9
BEGIN
SET #KODENYA = 'B' + LEFT('00',4-LEN(#KODE))+(#KODE)
END
ELSE IF #KODE >= 10 AND #KODE <=99
BEGIN
SET #KODENYA = 'B' + LEFT('0',4-LEN(#KODE))+(#KODE)
END
ELSE IF #KODE >= 100 AND #KODE <=999
BEGIN
SET #KODENYA = 'B' + LEFT('',4-LEN(#KODE))+(#KODE)
END
RETURN #KODENYA
The result is still the same and somehow I get #KODE if it was beyond 9 it return to null and SQL SERVER read it as 0.
Is there another way to create this kind of code in SQL SERVER?

There is no need for multiple if/case just simple FORMAT:
CREATE TABLE #tab(KODE INT);
INSERT INTO #tab(KODE) VALUES (1),(2),(10),(99),(101),(100),(999);
SELECT FORMAT(KODE, 'B00#')
FROM #tab;
LiveDemo
You can easily tweak it for longer codes by changing format string 'B000#'
And in your case:
CREATE FUNCTION [dbo].[AUTO_CODE]()
RETURNS CHAR(4)
AS
BEGIN
DECLARE #KODE INT = (SELECT COUNT(KODE_BARANG)FROM BARANG);
RETURN FORMAT(#KODE, 'B00#');
END
Warning:
You function may return duplicates/create gaps when many concurrent calls occur.
SqlFiddleDemo
Depending on your needs you may consider adding calculated column to your BARANG table:
CREATE TABLE BARANG(ID INT IDENTITY(1,1) PRIMARY KEY,
col2 VARCHAR(120) NOT NULL,
...
KODE AS (FORMAT(ID, 'B00#'))
);

Related

Simple ISEMPTY() function in SQL Server throws a non-boolean type error

I'm trying to write a simple ISEMPTY function in Microsoft SQL Server:
DROP FUNCTION IF EXISTS ISEMPTY;
GO
CREATE FUNCTION ISEMPTY
(#charsequence nvarchar(max))
RETURNS BIT
AS
BEGIN
DECLARE #result BIT;
IF (#charsequence IS NULL OR LEN(#charsequence) = 0)
SET #result = 1
ELSE
SET #result = 0;
RETURN #result;
END
GO
When I want to test it with:
SELECT CASE WHEN dbo.ISEMPTY('') THEN 'REACHED!' END;
I get the following error:
[S0001][4145] Line 1: An expression of non-boolean type specified in a context where a condition is expected, near 'THEN'.
What goes wrong here?
A boolean is expected after when in the case expression, but your function returns a bit.
Try this instead:
SELECT CASE WHEN dbo.ISEMPTY('') = 1 THEN 'REACHED!' END;
The function returns a number so you need a comparison with a number to get a boolean value
CREATE FUNCTION ISEMPTY( #charsequence nvarchar(max))
returns BIT AS
begin
DECLARE #result BIT;
IF (#charsequence IS NULL OR LEN(#charsequence) = 0 )
SET #result = 1;
ELSE
SET #result = 0;
RETURN #result;
end
GO
SELECT CASE WHEN dbo.ISEMPTY('') = 1 THEN 'REACHED!' END;
GO
| (No column name) |
| :--------------- |
| REACHED! |
db<>fiddle here

Calling function with table valued parameters in Postgres

I have been facing a problem from since morning and have spent many hours but failed to call below given function.
Function definition:
CREATE OR REPLACE FUNCTION public.proc_mc2cdnpf_insertupdatev3(
tblnotesv3 typupdate_notesv3,
tbldoclinks typupdate_guidparameter,
iuserid integer,
shtmltext character varying,
OUT snoteid character varying,
OUT inoteid integer,
OUT inoteactivityid integer)
RETURNS record
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
#variable_conflict use_variable
declare sNote VARCHAR;
declare sLoggedInUser VARCHAR(20);
declare dtCurrDateTime timestamp;
declare iCurrDate int;
declare iCurrTime INT;
declare iNewNoteID INT;
BEGIN
/*
proc_MC2CDNPF_InsertUpdateV3
2018-04-23 Dennis Sebenick
2018-04-23
- Initial creation of new proc for storing additional HTML text value.
- This proc is going to help bridge the old note system to a new note storage method
2018-04-25
- Added iNoteID / iNoteActivityID for output
2018-06-01
- Update to typUpdate_NotesV3 - removed additional CDN rows for long text
2091-05-08
Rupali Shah
web 1753-added RTRIM(isnull(NOTE_HDQTRS,'')) while creating sNoteID
*/
/******************************
** File: proc_MC2CDNPF_InsertUpdateV3
** Desc: Insert/Update account notes
** Auth: Rupali Shah
** Date: 2019-05-08
**************************
** Change History
**************************
** Date Dev JIRA Description
**2019-05-08 Rupali Shah Web 1753 -added RTRIM(isnull(NOTE_HDQTRS,'')) while creating sNoteID
*******************************/
SELECT dtCurrDateTime = fnGetDate();
SELECT iCurrDate = fnMC2DateToMC2(dtCurrDateTime);
SELECT iCurrTime = fnMC2DateTimeToMC2(dtCurrDateTime);
/*==========================================
Retrieve Update fields from parameter
============================================*/
select
NoteID,
NOTE_NOTES,
NOTE_LOGGEDINUSER,
coalesce(NOTE_ID, 0)
INTO SNoteID,sNote,sLoggedInUser,iNewNoteID
from
tblNotesV3
LIMIT 1;
/************************************************
2018-04-18 DKS
Added in to update new note table
*************************************************/
IF (iNewNoteID > 0)
THEN
BEGIN
IF (LENGTH(sNote) > 0)
THEN
BEGIN
UPDATE
NoteDetails
SET
sNote = sNote,
sNoteHTML = sHTMLText,
iNoteEditedBy = iUserID,
dtNoteEdited = dtCurrDateTime
WHERE
iNoteID = iNewNoteID;
IF (ROWCOUNT = 0)
THEN
BEGIN
INSERT INTO
NoteDetails
(
iNoteType,
sNote,
sNoteHTML,
iNoteEnteredBy,
dtNoteEntered
)
VALUES
( 9, -- iNoteType - int
sNote, -- sNote - VARCHAR(max)
sHTMLText, -- sNoteHTML - VARCHAR(max)
iUserID, -- iNoteEnteredBy - int
dtCurrDateTime
) RETURNING iNewNoteID;
END;
END IF;
END;
END IF;
END;
ELSE
BEGIN
-- Inserting a New Activity
-- 2018-04-18 DKS
-- - Insert to new note table.
IF (LENGTH(sNote) > 0)
THEN
BEGIN
INSERT INTO
NoteDetails
(
iNoteType,
sNote,
sNoteHTML,
iNoteEnteredBy,
dtNoteEntered
)
VALUES
( 9, -- iNoteType - int
sNote, -- sNote - VARCHAR(max)
sHTMLText, -- sNoteHTML - VARCHAR(max)
iUserID, -- iNoteEnteredBy - int
dtCurrDateTime
) RETURNING iNewNoteID;
END;
END IF;
END;
END IF;
/************************************************
End new note table insert / update
*************************************************/
IF EXISTS(SELECT * FROM MC2CDNPF WHERE MC2CDNPF.iNoteID = iNoteID)
THEN
BEGIN
UPDATE
MC2CDNPF
SET
CDNNOTES = '',
CDNFDATE = fnMC2DateToMC2(TblNotesUpdate.NOTE_DDATE),
CDNREASN = TblNotesUpdate.NOTE_REASN,
CDNPRIOR = TblNotesUpdate.NOTE_PRIOR,
CDNTAGGED = TblNotesUpdate.NOTE_TAGGED,
iNoteID = iNewNoteID
FROM
MC2CDNPF
JOIN
tblNotesV3 TblNotesUpdate
ON
MC2CDNPF.iNoteID = TblNotesUpdate.NOTE_ID
WHERE
MC2CDNPF.CDNDSEQN = 1;
END;
ELSE
BEGIN
SELECT
TRIM(coalesce(NOTE_CMPANY,'')) ||
TRIM(coalesce(NOTE_BUSNSS,'')) ||
TRIM(coalesce(NOTE_CUSNBR,'')) ||
TRIM(coalesce(NOTE_ENTITY,'')) ||
TRIM(coalesce(NOTE_HDQTRS,'')) ||
CAST( iCurrDate AS VARCHAR(8)) ||
CAST( iCurrTime AS VARCHAR(10))
INTO sNoteID
FROM
tblNotesV3
LIMIT 1;
INSERT INTO
MC2CDNPF
(
CDNDSEQN,
CDNNOTES,
CDNCMPANY,
CDNCUSNBR,
CDNBUSNSS,
CDNENTITY,
CDNHDQTRS,
CDNRPTCON,
CDNFULNME,
CDNAGNIDN,
CDNDDATE,
CDNDTIME,
CDNREASN,
CDNTUSER,
CDNADATE,
CDNTAGGED,
CDNFDATE,
CDNPRIOR,
CDNDTASRC,
CDNODATE,
CDNOTIME,
iNoteID
)
SELECT
1,
'', -- 6/1/2018 DKS - no longer storing note in MC2CDNPF
coalesce(NOTE_CMPANY,''),
coalesce(NOTE_CUSNBR,''),
coalesce(NOTE_BUSNSS,''),
coalesce(NOTE_ENTITY,''),
coalesce(NOTE_HDQTRS,''),
coalesce(NOTE_RPTCON,''),
NOTE_FULNME,
coalesce(NOTE_AGNIDN,''),
iCurrDate,
iCurrTime,
NOTE_REASN,
NOTE_TUSER,
iCurrDate,
coalesce(NOTE_TAGGED,''),
iCurrDate,
NOTE_PRIOR,
coalesce(NOTE_DTASRC,''),
iCurrDate,
iCurrTime,
iNewNoteID
FROM
tblNotesV3 TblSource;
END;
END IF;
-- There are attachments to link
IF EXISTS(SELECT * FROM tblDocLinks)
THEN
BEGIN
CALL public.proc_Documents_AddLinkMultiple_LinkID (tblDocLinks, 9, 0, sNoteID, iUserID);
END;
END IF;
iNoteID := iNewNoteID;
iNoteActivityID := 0;
END;
$BODY$;
I am trying to call my function in following two ways:
Method1:
SELECT public.proc_MC2CDNPF_InsertUpdateV3
(
(SELECT w::typupdate_notesv3 FROM (TABLE tblnotesv31) w ) ,
(SELECT w1::typupdate_guidparameter FROM (TABLE tbldoclinks1) w1 ) ,
1,
'test text'
)
But it fails with following error:
ERROR: query has no destination for result data
HINT: If you want to
discard the results of a SELECT, use PERFORM instead. CONTEXT:
PL/pgSQL function
proc_mc2cdnpf_insertupdatev3(typupdate_notesv3,typupdate_guidparameter,integer,character
varying) line 41 at SQL statement SQL state: 42601
Method2:
SELECT *
from proc_MC2CDNPF_InsertUpdateV3
(
(SELECT w::typupdate_notesv3 FROM (TABLE tblnotesv31) w ) ,
(SELECT w1::typupdate_guidparameter FROM (TABLE tbldoclinks1) w1 ) ,
1,
'test text'
)
Again it failed saying:
ERROR: query has no destination for result data HINT: If you want to
discard the results of a SELECT, use PERFORM instead. CONTEXT:
PL/pgSQL function
proc_mc2cdnpf_insertupdatev3(typupdate_notesv3,typupdate_guidparameter,integer,character
varying) line 41 at SQL statement SQL state: 42601
Can please someone help me out that what's actually wrong with my function call?
Starting at line 41 (as the error message told you) you got:
SELECT dtCurrDateTime = fnGetDate();
SELECT iCurrDate = fnMC2DateToMC2(dtCurrDateTime);
SELECT iCurrTime = fnMC2DateTimeToMC2(dtCurrDateTime);
I assume you want to set the variables there. But you're doing it wrong. (It looks like you tried to use SQL Server syntax. Is this an attempt to port a function from SQL Server to Postgres? There are also BEGIN ... END blocks for IFs and ELSEs, which are unnecessary (but harmless) in Postgres but needed in SQL Server.)
Either use INTO:
SELECT fnGetDate() INTO dtCurrDateTime;
SELECT fnMC2DateToMC2(dtCurrDateTime) INTO iCurrDate;
SELECT fnMC2DateTimeToMC2(dtCurrDateTime) INTO iCurrTime;
Or, since you're not actually querying a table, simple assignments should work too:
dtCurrDateTime = fnGetDate();
iCurrDate = fnMC2DateToMC2(dtCurrDateTime);
iCurrTime = fnMC2DateTimeToMC2(dtCurrDateTime);
There might be other lines with the same mistake, you should check the whole code.

Algorithm for auto generated series number in sql

I want to make an algorithm for generate next series number by specified last series number in sql like below:
Last Number Next Number
> AAAA095 AAAA096
> AAAA999 AAAB001
> AAAB001 AAAB002
> AAAZ999 AABA001
After some try, Finally i got an algorithm & create it to SQL Scalar-valued function for this question as below
CREATE FUNCTION GetNextSeries ( #lastSeriesNo VARCHAR(8))
RETURNS VARCHAR(8)
AS
BEGIN
DECLARE #nextSeriesNo VARCHAR(8)
DECLARE #CHAR1 CHAR=SUBSTRING(#lastSeriesNo,1,1)
DECLARE #CHAR2 CHAR=SUBSTRING(#lastSeriesNo,2,1)
DECLARE #CHAR3 CHAR=SUBSTRING(#lastSeriesNo,3,1)
DECLARE #CHAR4 CHAR=SUBSTRING(#lastSeriesNo,4,1)
DECLARE #n INT=SUBSTRING(#lastSeriesNo,5,3)
SET #n = #n + 1
IF(#n>999)
BEGIN
SET #n=1
IF(#CHAR4<>'Z')
BEGIN
SET #CHAR4=CHAR(UNICODE(#CHAR4)+1)
END
ELSE IF(#CHAR3<>'Z')
BEGIN
SET #CHAR4='A'
SET #CHAR3=CHAR(UNICODE(#CHAR3)+1)
END
ELSE IF(#CHAR2<>'Z')
BEGIN
SET #CHAR4='A'
SET #CHAR3='A'
SET #CHAR2=CHAR(UNICODE(#CHAR2)+1)
END
ELSE IF(#CHAR1<>'Z')
BEGIN
SET #CHAR4='A'
SET #CHAR3='A'
SET #CHAR2='A'
SET #CHAR1=CHAR(UNICODE(#CHAR1)+1)
END
END
SET #nextSeriesNo=#CHAR1+#CHAR2+#CHAR3+#CHAR4+(CASE LEN(#n) WHEN 1 THEN '00' WHEN 2 THEN '0' ELSE '' END)+convert(VARCHAR(3),#n)
RETURN #nextSeriesNo
END

SQL Server insert loop of strings

Thank you in advance for your help here.
I want to insert incremental numbers as strings to load some bulk test numbers into a db, here is what i'm using:
Declare
#Serialcounter bigint
set #Serialcounter = 0
while #Serialcounter < 10
insert into [TrackTrace].[dbo].[TAB_ELEMENT] ([Serial], [Batch], [Batch_Id], [QCSample], [StationID])
values(Convert(varchar(60), #Serialcounter), 'test', 8989, 0, 1)
set #Serialcounter = (#Serialcounter + 1)
but when I do this it does not increment the counter and I just insert duplicate numbers and do not stop. I think my problem is that my variable is incremented outside of the while loop, but I am not sure how to rectify this.
Declare
#Serialcounter bigint
set #Serialcounter = 0
while #Serialcounter < 10
BEGIN
PRINT #Serialcounter
--insert into [TrackTrace].[dbo].[TAB_ELEMENT]
--([Serial]
--,[Batch]
--,[Batch_Id]
--,[QCSample]
--,[StationID])
--Values(Convert(varchar(60),#Serialcounter),'test',8989,0,1)
set #Serialcounter = (#Serialcounter +1 )
END
You not giving begin and end so as for all loops only first statement is considered
I was missing BEGIN and END statements
DECLARE
#Serialcounter BIGINT
SET #Serialcounter = 0
WHILE #Serialcounter < 10
BEGIN -- here
INSERT INTO [TrackTrace].[dbo].[TAB_ELEMENT]
([Serial]
,[Batch]
,[Batch_Id]
,[QCSample]
,[StationID])
VALUES(Convert(varchar(60),#Serialcounter),'test',8989,0,1)
SET #Serialcounter = (#Serialcounter +1 )
END -- and here

SQL multiple if statements, same result set, different argument

I am writing a stored proc that calculates a WHOLE bunch of different things, but I have a bit in it, that is repeated about 9 times.
eg:
if #argA = 1 (true)
select Count(samples) from dbo.X where type = #argAType
if #argB = 1 (true)
select Count(samples) from dbo.X where type = #argBType
if #argC = 1
select Count(samples) from dbo.X where type = #argCType
and so on...
how can I write a function (or something similar) that I can pass in a bit (true or false), and other argument, and only return the result set if true???
Is this what you're looking for? This is the best I can deduce based on the question as it's currently posted.
SELECT COUNT(samples)
FROM dbo.X
WHERE
(type=#argAType AND #argA=1)
OR
(type=#argBType AND #argB=1)
OR
(type=#argCType AND #argC=1)
In function form, I think this is right:
CREATE FUNCTION GetCount(#n AS BIGINT) RETURNS BIGINT
AS
BEGIN
DECLARE #count BIGINT
SELECT #count = COUNT(samples)
FROM dbo.X
WHERE
(type=#argAType AND #argA=1)
OR
(type=#argBType AND #argB=1)
OR
(type=#argCType AND #argC=1)
RETURN #count
END