At a Format Constraint to A Create Table Statement - sql-server

I am creating a table in SQL Server for one of my customers that is needing an Access DB converted to SQL Server. ON the tables Access has masked a column a certain way. They have a number lets say TP001111 and when I pull the value into SQL Server I get 1111. I have a table called VendorNumber and I need to format this number.
CREATE TABLE VendorNumber
(
V_ID NVARCHAR(8) NOT NULL PRIMARY KEY,
V_Name NVARCHAR(30) NOT NULL
)
I have tried researching how to do this and I can't find a good example. What is the best way to have this value formatted when it is inserted into the table. I need to have it inserted as TP001111. The current code I have to format the column is:
UPDATE VendorNumber
SET V_ID = 'TP' + RIGHT((REPLICATE('0',6) + TPPRM_ID),6)

Related

SQL Server : identity and autoincrement for varchar

This is my first question on this platform. I am working on a database project. I want to use autoincrement for my primary key for id, but also want to add an alphabet before it. Are there other ways to do it apart from using 2 columns declaring one as identity and casting the other? I have worked with stored procedures and triggers.
Thank you
PS: I want to do it using one column if possible
You won't be able to do this with just one column.
The best solution is to use
an ID INT IDENTITY(1,1) column to get SQL Server to handle the automatic increment of your numeric value
a computed, persisted column to convert that numeric value to the value you need
So try this:
CREATE TABLE dbo.tblCompany
(
ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
CompanyID AS 'CMP-' + RIGHT('00000' + CAST(ID AS VARCHAR(5)), 5) PERSISTED,
.... your other columns here....
)
Now, every time you insert a row into tblCompany without specifying values for ID or CompanyID:
INSERT INTO dbo.tblCompany(Col1, Col2, ..., ColN)
VALUES (Val1, Val2, ....., ValN)
then SQL Server will increase your ID value, and CompanyID will contain values like CMP-00001, CMP-00002,...... and so on - automatically. The CompanyID column will be fill automatically, by SQL Server, upon inserting a new row - so there's no need for triggers or stored procedures or anything else - just this declaration in your table definition.
UPDATE: if you're using SQL Server 2012 or newer, you can do it with just one column - if you also create a SEQUENCE - like this:
CREATE SEQUENCE SEQ_CompanyID
AS INT
START WITH 1000
INCREMENT BY 1;
CREATE TABLE dbo.Company
(
CompanyID VARCHAR(20) NOT NULL
CONSTRAINT DF_CompanyID
DEFAULT('CMP-' + CAST(NEXT VALUE FOR dbo.SEQ_CompanyID AS VARCHAR(10))),
CompanyName VARCHAR(100) NOT NULL,
----- other columns here
)
Now if you make sure to insert with omitting the CompanyID column in the insert statement, like this:
INSERT INTO dbo.Company (CompanyName)
VALUES ('Company #1'), ('Company ABC'), ('Company Three');
then you get CMP-1001', 'CMP-1002 etc. as your CompanyID, again, automatically handled by SQL Server upon inserting a new row.

What is the best practice to insert multiple records to DB and get multiple records from DB in single instance using BizTalk?

I want to develop a BizTalk orchestration. Which should insert multiple records into multiple DB tables and retrieve inserted records from multiple DB tables, in single instance of orchestration. For this requirement, I'm able to insert the data in one instance, but seeing difficulty to retrieve the inserted data for that instance, as all the records has unique values for each record. For my situation, I should use stored procedures, to apply some other business logic. So I have 2 different methods by using "Wcf_Custom Adapter composite feature" by calling stored procedures, as stated below.
-> Method1
I have to develop a Stored procedure, which takes LoadDate("2016-05-12 10:11:22.147") as parameter along with inserting values and it will take care of inserting the records for that instance, by keeping the given LoadDate. Then immediately it will call Get stored procedure, which takes the LoadDate("2016-05-12 10:11:22.147") as parameter, then it will retrieve the recently inserted records from DB based on LoadDate value.
I know, Retrieving the data based on a date value from sql server is a bad practice and it will give performance issues too.
-> Method2
I'll design the inserting tables, with bool data type column name "New" and value will be 0 or 1. I'll develop a Insert Stored procedure, which inserts the data by giving the "New" column value as "1". Then immediately it will call Get stored procedure, which will not take no parameters, then it will retrieve the recently inserted records which are having "New" column indicator "1" from DB tables. Once it retrieves the data, then it will update "New" column value to "0".
I prefer this method2. But, do we have better option?
As #johns-305 mentioned in his comment. You shall use table value param in your sp. and assembly all your data in orchestration then make a call to this sp.
A sample sp may like below:
CREATE TYPE [dbo].[SampleDataTable_Type] AS TABLE(
[ID] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)
GO
CREATE PROCEDURE [dbo].[sp_InsertSampleTableData]
(
#LoadDate DATETIME,
#data [SampleDataTable_Type] READONLY
)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO your_table(id, name,)
SELECT id, name FROM #data;
--Do whatever you want
SET NOCOUNT OFF
END
GO
I think your stored procedure may look like this:
create procedure myProc
#a int, #b varchar(100)
as
insert myTable(a,b,c)
OUTPUT inserted.* --this line
select a,b,c
from somewhere
where a=#a and b=#b

SQL Server time stamp column insertion or updation possible explicitly?

Is there any way to provide an explicit value for time stamp column in a table in SQL server? I am aware it is not datetime column but I want to know whether there is any way to insert or update it explicitly.
You cannot insert/update to timestamp column explicitly. They are generated automatically, when you perform insert/update to the table.
Because the timestamps appear to be representations of timestamps created by the database when you inserted or updated the column, in effect you would have to change the original timestamp created by the database in order to define them explicitly.
From your second comment I appreciate that you might have data coming in which is already timestamped and you just want those represented on your table in the same way as inserting data with "set identity_insert on" .
The answer would be to select the existing table into another table then add the incoming data. If you run the code below I think you'll see what I mean.
create table abc
(
col1 int, timestamp
)
go
insert into abc(col1) values (1)
go
select col1,convert(varbinary,timestamp) timestamp# into def from abc
go
select * from abc
select * from def
As far as I know the timestamp represents a row version number (which is why they change when you update a value in the row because you are creating another version of the row). There might be a date in the transaction log which states when this version of the row came into being. I don't consider it possible to directly convert timestamp to datetime.
Well..the only other idea I have is to add another column and then select the timestamp values into that! The weirdest thing, in doing this it takes the last character back one! See what you think.
drop table abc
go
create table abc
(
col1 int, timestamp
)
go
insert into abc(col1) values (1)
go
alter table abc add timestamp# varbinary(18)
go
update abc set timestamp# = convert(varbinary,timestamp)
Generaly speaking, when creating a table I would include a column which defaults to datetime, this way you have a datetime when each row is created.
Like this:
drop table def
go
create table def
(
col1 int,
idt datetime default getdate()
)
If you insert a value into col1 and do not include the idt in your column list in the insert statement the idt column will default to the datetime you inserted the value.
Like this:
insert into def (col1) values (1)

Alter Column: option to specify conversion function?

I have a column of type float that contains phone numbers - I'm aware that this is bad, so I want to convert the column from float to nvarchar(max), converting the data appropriately so as not to lose data.
The conversion can apparently be handled correctly using the STR function (suggested here), but I'm not sure how to go about changing the column type and performing the conversion without creating a temporary column. I don't want to use a temporary column because we are doing this automatically a bunch of times in future and don't want to encounter performance impact from page splits (suggested here)
In Postgres you can add a "USING" option to your ALTER COLUMN statement that specifies how to convert the existing data. I can't find anything like this for TSQL. Is there a way I can do this in place?
Postgres example:
...ALTER COLUMN <column> TYPE <type> USING <func>(<column>);
Rather than use a temporary column in your table, use a (temporary) column in a temporary table. In short:
Create temp table with PK of your table + column you want to change (in the correct data type, of course)
select data into temp table using your conversion method
Change data type in actual table
Update actual table from temp table values
If the table is large, I'd suggest doing this in batches. Of course, if the table isn't large, worrying about page splits is premature optimization since doing a complete rebuild of the table and its indexes after the conversion would be cheap. Another question is: why nvarchar(max)? The data is phone numbers. Last time I checked, phone numbers were fairly short (certainly less than the 2 Gb that nvarchar(max) can hold) and non-unicode. Do some domain modeling to figure out the appropriate data size and you'll thank me later. Lastly, why would you do this "automatically a bunch of times in future"? Why not have the correct data type and insert the right values?
In sqlSever:
CREATE TABLE dbo.Employee
(
EmployeeID INT IDENTITY (1,1) NOT NULL
,FirstName VARCHAR(50) NULL
,MiddleName VARCHAR(50) NULL
,LastName VARCHAR(50) NULL
,DateHired datetime NOT NULL
)
-- Change the datatype to support 100 characters and make NOT NULL
ALTER TABLE dbo.Employee
ALTER COLUMN FirstName VARCHAR(100) NOT NULL
-- Change datatype and allow NULLs for DateHired
ALTER TABLE dbo.Employee
ALTER COLUMN DateHired SMALLDATETIME NULL
-- Set SPARSE columns for Middle Name (sql server 2008 only)
ALTER TABLE dbo.Employee
ALTER COLUMN MiddleName VARCHAR(100) SPARSE NULL
http://sqlserverplanet.com/ddl/alter-table-alter-column

Is it possible to alter a SQL Server table column datatype from bigint to varchar after it has been populated?

I have a SQL Server 2008 table which contains an external user reference currently stored as a bigint - the userid from the external table. I want to extend this to allow email address, open ID etc to be used as the external identifier. Is it possible to alter the column datatype from bigint to varchar without affecting any of the existing data?
Yes, that should be possible, no problem - as long as you make your VARCHAR field big enough to hold you BIGINT values :-)
You'd have to use something like this T-SQL:
ALTER TABLE dbo.YourTable
ALTER COLUMN YourColumnName VARCHAR(50) -- or whatever you want
and that should be it! Since all BIGINT values can be converted into a string, that command should work just fine and without any danger of losing data.

Resources