SQL Server - Enforcing the number of digits on an int - sql

I have a unique ID that I am generating program-side in the format CCYYMMDDxxxx, where xxxx is a 4 digit string that will auto increment, starting from 0001.
To calculate the next element, I have wrote part of a query which gets those 4 digits from the string using substring.
DECLARE #number int, #nextstring varchar(4)
SET #number = (SELECT CONVERT(int, SUBSTRING(Payment_ID, 9, 4), 103) FROM Orders)
I need to be able to increment it by 1, but keep it in 4 digit format. I came across the 'right' keyword, but I don't know how many 0's ill need to put in front of it.
Is there a nice way to do this without a bunch of IF's? Of course, I could calculate the length and put the respective number of 0's at the start, but that doesn't account for 9, 99, and 999.

I really think that an identity column is the best way to handle this . . . then assign the sequential number afterwards.
But, if you want to do this, you need to left pad the number. Here is a method to get the next id based on values in the table:
SELECT (LEFT(MAX(payment_id), 8) +
RIGHT('0000' + CAST(CAST(RIGHT(MAX(payment_id), 4) as int) + 1 as VARCHAR(255))
)
FROM Orders;
This does not verify that the id is long enough. Let me repeat: I think it is much better to use an identity column as the id and then construct whatever attributes you want (such as the number within a day) when you need that information.

Related

How to anonymize data in SQL?

I need to anonymize a variable in SQL data (VAR NAME = "ArId").
The variable contains 10 numbers + 1 letter + 2 numbers. I need to randomize the 10 first numbers and then keep the letter + the last two numbers.
I have tried the rand() function, but this randomize the whole value.
SELECT TOP 1000 *
FROM [XXXXXXXXXXX].[XXXXXXXXXX].[XXXXX.TEST]
I have only loaded the data.
EDIT (from "answer"):
I have tried: UPDATE someTable
SET someColumn = CONCAT(CAST(RAND() * 10000000000 as BIGINT), RIGHT(someColumn, 3))
However as i am totally new to SQL i don't know how to make this work. I put 'someColumn = new column name for the variable i am crating. RIGHT(someColumn) = the column i am changing. When i do that i get the message that the right function requires 2 arguments??
Example for Zohar: I have a variable containing for example: 1724981628R01On all these values in this variable i would like to randomize the first 10 letters and keep the last three (R01). How can i do that?
A couple things. First, your conversion to a big int does not guarantee that the results has the right number of characters.
Second, rand() is constant for all rows of the query. Try this version:
UPDATE someTable
SET someColumn = CONCAT(FORMAT(RAND(CHECKSUM(NEWID())
), '0000000000'
),
RIGHT(someColumn, 3)
);

update multiple rows with random 9 digit number using rand() function

I am trying to update multiple rows with random 9 digit number using the following code.
UPDATE SGT_EMPLOYER
SET SSN = (CONVERT(NUMERIC(10,0),RAND() * 899999999) + 100000000)
WHERE EMPLOYER_ACCOUNT_ID = 123456789;
Expected result: the query should update 300 rows with 300 random 9 digit numbers.
Actual: query is updating 300 rows with same number as the ran() function is executing only once.
Please help. Thank You.
As you already figured out yourself, RAND is a run-time constant function in SQL Server. It means that it is called once per statement and the generated value is used for each affected row.
There are other functions that are called for each row. Often people use NEWID usually together with CHECKSUM as a substitute for a random number, but I would not recommend it because the distribution of such random numbers is likely to be poor.
There is a good function specifically designed to generate random numbers: CRYPT_GEN_RANDOM. It is available since at least SQL Server 2008.
It generates a given number of random bytes.
In your case it would be convenient to have a random number as a float value in the range of [0;1], same as the value returned by RAND.
So, CRYPT_GEN_RANDOM(4) generates 4 random bytes as varbinary.
Convert them to int, divide by the maximum value of 32-bit integer (4294967295) and add 0.5 to shift the range from [-0.5;+0.5] to [0;1]:
(CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5)
Your query becomes:
UPDATE SGT_EMPLOYER
SET SSN =
CONVERT(NUMERIC(10,0),
(CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 899999999.0 + 100000000.0)
WHERE EMPLOYER_ACCOUNT_ID = 123456789;
Yes, the rand() line will only be executed once, before the rows are being updated, not every time a row is updated.
You can use a Stored Procedure to update every row with (CONVERT(NUMERIC(10,0),RAND() * 899999999) + 100000000).
Sean Lange is 100% correct. However, if you want to quickly mask your SSN, perhaps the following using HashBytes() may help.
Example
Declare #Table table (SSN varchar(25))
Insert into #Table values
('070-99-12345'),
('123-45-67890')
Select SSN
,AsInt = abs(cast(HashBytes('MD5', SSN) as int))
From #Table
Returns
SSN AsInt
070-99-12345 508860145
123-45-67890 843256257

How to insert the same random number for another column's value?

Within my table 'SERVICE_TICKET' are two columns, namely 'Defect_Description' and 'Defect_Description_Code'.
I'd like to populate the second column with random numbers between 1000000 and 9999999 (7-digit-number). However, the random number should be the same for equal values within the first column. So for example if the 'Defect_Description'= 'microphone for hands-free device',the'Defect_Description_Code'should always equal the same arbitrary number, e.g.'8374917'`.
I came up with the following expression, but this creates a diffirent number for each 'Defect_Description'. What do I need to change in order to get the same number for each of these?
UPDATE dbo.SERVICE_TICKET
SET Defect_Description_Code =
CASE Defect_Description
WHEN 'microphone for hands-free device' THEN (ABS(CHECKSUM(NewId())) % 1111111 + 9999999)
ELSE '-'
END
I think you want to avoid newid() in this case. I would recommend simply using Defect_Desription itself.
The following query also fixes the logic to get the 7 digit number:
UPDATE dbo.SERVICE_TICKET
SET Defect_Description_Code = ABS(CHECKSUM(Defect_Description)) % 9000000 + 1000000;

How to implement MAX function on a text column in SQL Server?

I'm using SQL Server 2005 and have a column that contains serial numbers, which are nvarchar(50).
My problem is selecting max(serial_no) from the table. The serial numbers used to have a length of 7 only but new ones are now 15. Whenever I select the max, I get a result with a length of 7, which means that data is old. I also can't filter it to only select from records which have a length of 15 because then i'll miss some other data on my query.
Old serial numbers look like this...
'SNGD001'
..., and new ones look like this:
'SN14ABCD0000001'
Edit: I tried creating a dummy table without the old serial numbers (5 characters long), and I'm getting correct results.
As has been mentioned, your question is a bit hard to follow. If the max value could be either one of your old serial numbers or one of your new ones, I believe the following should do the trick:
SELECT MAX(RIGHT('0000000' + REVERSE(LEFT(REVERSE(YourTextColumn), PATINDEX('%[a-z]%', REVERSE(YourTextColumn)) - 1)), 7))
FROM YourTable
It finds the first non numeric character from the right keeping everything to the right of that. It then left zero pads the resulting numeric string to 7 characters and applies the MAX function.
Your question is a little tough to follow without good sample data to get a bearing on. I suggest for future, you show a few more examples of data to get better context, especially with sequencing. Now, your desire to get the MAX() of a "serial_no" from your table appears you need so you get detect the next sequential serial number to assign. However, your serial number appears to be a concatenation of a prefix string and then sequential. So, if I were to look at your brief data MIGHT HAVE BEEN along the lines of (last 3 digits are the sequential serializations)
SNGD001
SNGD002
SNGD003
...
SNGD389, etc...
and your new data with the last (last 7 digits are sequential serializations)
SN14ABCD0000001
SN14ABCD0000002
SN14ABCD0000003
...
SN14ABCD0002837
If this is correct, then you basically need to look at the max based on the leading 3 or 8 characters of the string PLUS the converted suffix numeric sequence. For starters, lets go with that to see if we are on the correct track or not, then you can easily concatenate the prefix and sequence number together at the end for determining the next available number.
So, based on the above samples, you may want to know that for each prefix, the last number of
SNGD389 and
SN14ABCD0002837 respective per their prefix
If the above is correct, I might start with...
select
case when LEN( RTRIM( yt.serial_no )) = 7
then LEFT( yt.serial_no, 4 )
else LEFT( yt.serial_no, 8 ) end as SerialPrefix,
MAX( case when LEN( RTRIM( yt.serial_no )) = 7
then CONVERT(INT, RIGHT( yt.serial_no, 3 ))
else CONVERT(INT, RIGHT( yt.serial_no, 7 )) end ) as SerialSequence
from
YourTable yt
group by
case when LEN( RTRIM( yt.serial_no )) = 7
then LEFT( yt.serial_no, 4 )
else LEFT( yt.serial_no, 8 ) end as SerialPrefix
Which would result in (based on sample data I presented)
SerialPrefix SerialSequence
SNGD 389
SN14ABCD 0002837
Of which since the serial sequence column being numeric, you could add 1 to it, then left-zero fill a string and concatenate the two back together such as to create
SNGD390
SN14ABCD0002838

How to generate alphanumeric tokens in SQL Server?

I am looking to generate soem alpha numeric tokens. Is there a function that can do to generate set length tokens?
You can do this and then take a substring of it of whatever length you need:
select replace(newid(), '-', '')
E.g., for eight characters:
select substring(replace(newid(), '-', ''), 1, 8)
I have done this by combining a unique id from the table with a random number:
update [table]
set token = cast([id] as varchar(10)) + cast(cast(round((rand() * 500000000.0), 0) as int) as varchar(10))
Adjust the varchar sizes and the multiplication factor to get the toekn size you need. If you need a precise size, make the resulting string a little too long and use substring to set the length.
This is not crytographically strong, but it works for me in most cases. Using the id field from the table guarantees that the token is unique, and the random number makes it difficult to guess.
Another possible solution (for SQL Server, i think NEWID() is not available in other DBMS but use another similar function):
SELECT CONVERT(VARCHAR(10), RIGHT(NEWID(), 5))
The NEWID() function returns a Alpha numeric ID generated by SQL Server which you can use in the way you need.
Works well for me.