Convert table column data type from image to varbinary - sql

I have a table like:
create table tbl (
id int,
data image
)
It's found that the column data have very small size, which can be stored in varbinary(200)
So the new table would be,
create table tbl (
id int,
data varbinary(200)
)
How can I migrate this table to new design without loosing the data in it.

Just do two separate ALTER TABLEs, since you can only convert image to varbinary(max), but you can, afterwards, change its length:
create table tbl (
id int,
data image
)
go
insert into tbl(id,data) values
(1,0x0101010101),
(2,0x0204081632)
go
alter table tbl alter column data varbinary(max)
go
alter table tbl alter column data varbinary(200)
go
select * from tbl
Result:
id data
----------- ---------------
1 0x0101010101
2 0x0204081632

You can use this ALTER statement to convert existing column IMAGE to VARBINARY(MAX). Refer Here
ALTER Table tbl ALTER COLUMN DATA VARBINARY(MAX)
After this conversion, you are surely, get your data backout.
NOTE:- Don't forgot to take backup before execution.
The IMAGE datatype has been deprecated in future version SQL SERVER, and needs to be converted to VARBINARY(MAX) wherever possible.

How about you create a NewTable with the varbinary, then copy the data from the OldTable into it?
INSERT INTO [dbo].[NewTable] ([id], [data])
SELECT [id], [image] FROM [dbo].[OldTable]

First of all from BOL:
image: Variable-length binary data from 0 through 2^31-1
(2,147,483,647) bytes.
The image data type is essentially an alias for varbinary (2GB), so converting it to a varbinary(max) should not lead to data loss.
But to be sure:
back up your existing data
add a new field (varbinary(max))
copy data from old field to new field
swap the fields with sp_rename
test
after successful test, drop the old column

Related

Replace random varbinary data in middle of column (MSSQL)

I have a inventory column with various data and multiple rows, it's necessary replace random varbinary data in middle of column.
Example of Inventory column:
Screenshot
For example this:
0x0500420000000000005000FFFFFFFFFF56730E64FFFFFFFFFFFFFFFFFFFFFFFF0400180000000000006000FFFFFFFFFF56730E72FFFFFFFFFFFFFFFFFFFFFFFF04001E0000000000007000FFFFFFFFFF56730E5EFFFFFFFFFFFFFFFFFFFFFFFF
Need to be changed to:
0x0500420000000000005000FFFFFFFFFF56730E64FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF04001E0000000000007000FFFFFFFFFF56730E5EFFFFFFFFFFFFFFFFFFFFFFFF
I know how to change static data like here. But here is many rows and in every row data is different. It's possible maybe change data somehow by length? Start length position is 67, end 131.
But here is many rows and in every row data is different. It's possible maybe change data somehow by length? Start length position is 67, end 131.
You can use STUFF or SUBSTRING and + to rewrite the entire blob, or you can update it in-place, see Updating Blobs, eg
drop table if exists #temp
go
create table #temp(id int, blob varbinary(max))
insert into #temp(id,blob) values (1,0x0500420000000000005000FFFFFFFFFF56730E64FFFFFFFFFFFFFFFFFFFFFFFF0400180000000000006000FFFFFFFFFF56730E72FFFFFFFFFFFFFFFFFFFFFFFF04001E0000000000007000FFFFFFFFFF56730E5EFFFFFFFFFFFFFFFFFFFFFFFF)
declare #newBytes varbinary(100) = 0xAAAAAAAAAAAA
--only for varbinary(max) but updates in-place
update #temp
set blob.write(#newBytes,10,datalength(#newBytes))
--for varbinary(max) or varbinary(n) replace the whole value
update #temp
set blob = cast(STUFF(blob,30,datalength(#newBytes),#newBytes) as varbinary(max))
select * from #temp

Convert column from varchar to datetime and update it in the table

I have a question related to the conversion of varchar to datetime.
This topic was covered already in the thread
SQL Server Convert Varchar to Datetime
but I would like to advance it bit further.
I have performed BULK INSERT into predefined tables where VARCHAR(255)
is the destination. I have a table dbo.USR_02_ALL_RAW and the field GLTGB which
holds strings in the following format: 07/16/2016.
I can convert it as a single string by the following code:
DECLARE #Date varchar(255)
set #Date= '07/16/2016'
SELECT CONVERT(datetime,RIGHT(#Date,4)+LEFT(#Date,2)+SUBSTRING(#Date,4,2))
and it gives me a result:
2016-07-16 00:00:00.000
However I would like to pass to the code the whole field GLTGB from the table
dbo.USR_02_ALL_RAW, convert it from VARCHAR into DATETIME and update the field GLTGB with these results.(converting the whole field from varchar to datetime)
Thank you!
First clear this, you want to Bulk insert or Bulk update. Since you already have a column GLTGB. If you want to update the value only.
update tab set GLTGB =
CONVERT(datetime,RIGHT(GLTGB,4)+LEFT(GLTGB,2)+SUBSTRING(GLTGB,4,2))
Or
If you want to update the field from varchar to datetime. Then process is little bit lengthy.
Alter table tab add newcol datetime --- Add new datetime type column
update tab set newcol =
CONVERT(datetime,RIGHT(GLTGB,4)+LEFT(GLTGB,2)+SUBSTRING(GLTGB,4,2)) --- update value in new column
Alter table tab drop column GLTGB --- drop GLGTB column
Alter table tab add GLGTB datetime --- add GLGTB column as datetime type
update tab set GLGTB = newcol --- update value from GLGTB from newcol
Alter table tab drop column newcol ---- remove unnecessary newcol
If you convert a value to datetime, then update the same database column it came from with the value then, since that column is still varchar, SQL will have to convert the value back to varchar again in order to store it. So you can't achieve anything useful with that kind of simple approach.
f you want to actually change the data type of the column, and also convert all the values, then I think you need to go through the following process:
1) Create a new varchar column in your table (which will be temporary)
2) copy all the data values from the GLTGB column into the new column (using an UPDATE statement)
3) Drop the GLTGB column
4) Re-create it with the same name but with datetime type
5) Use an UPDATE statement to re-populate the new GLTGB column from your temporary column
6) Finally, drop the temporary column
There may be a simpler way but that seems like the obvious process.
You can use the following code for updating but before that, you need to change the data type of your field to DateTime
update dbo.USR_02_ALL_RAW
set GLTGB=cast(CONVERT(datetime,RIGHT(#Date,4)+LEFT(#Date,2)+SUBSTRING(#Date,4,2)) as datetime)

How to change column datatype in SQL Server and convert previous type without losing data

I have a SQL Server database and I'd like to change column types to reduce it's size:
I have a string Name Varchar(100) and want to convert it to Varchar(50) AND I have to move data to it (data will fit into varchar(50))
I have a Varchar(30) that represents time as epoch time (eg. 1508752574). I want to change the type to Datetime and convert data form Varchar(30) to Datetime and then put it in Datetime
Can I do it without losing data?
Point 1
ALTER TABLE dbo.table_name ALTER COLUMN name VARCHAR(50);
Point 2
You would need to add another column of type Datetime and update the column with the Datetime equivalent of the epoch_time_col.
ALTER TABLE dbo.table_name ADD epoch_time_dt DATETIME NULL;
UPDATE dbo.table_name SET epoch_time_dt = DATEADD(SECOND, epoch_time_col, '19700101');
If you need, you can then drop the old column
ALTER TABLE dbo.table_name DROP COLUMN epoch_time_col ;
Create new columns:
Alter table MyTable
add NewColumn1 varchar(50);
Alter table MyTable
add NewColumn2 datetime;
Fill with data:
update MyTable
set NewColumn1 = left(Name,50),
NewColumn2 = dateadd(s, epochcol1, '19700101');
You can then drop the old columns and rename the new ones
I don't see any loss of data issue..
I have a string Name Varchar(100) and want to convert it to Varchar(50) AND I have to move data to it (data will fit varchar(50))
There will be no data loss,if your data fits in varchar(50) data type,if the data doesn't fit the insert will fail and you can rectify that
Also i don't see any issue with data loss in converting your epoch value to datetime with below approach,since you are just adding seconds
Select
dateadd(S, [unixtime], '1970-01-01')
From [Table]

Convert datetime column to smallint

I have a column called MyYear that is of type datetime. It only stores the year though, so I want to change it to smallint.
When I try to run this:
ALTER TABLE MyTable
ALTER COLUMN MyYear smallint
I get this error:
Implicit conversion from data type datetime to smallint is not
allowed. Use the CONVERT function to run this query.
When I run this:
UPDATE MyTable
set MyYear=YEAR(MyYear)
It does something funky and sets all the years to 1905.
I am using SQL Server.
You cannot convert a DATETIME to a SMALLINT, you will need to:
ALTER TABLE MyTable
ADD MyActualYear SMALLINT
GO
UPDATE MyTable SET MyActualYear = CAST(YEAR(MyYear) AS SMALLINT)
GO
ALTER TABLE MyTable
DROP COLUMN MyYear
GO
EXEC sp_RENAME 'MyTable.[MyActualYear]' , 'MyYear', 'COLUMN'
GO
i.e. add a new temporary column, update it with the value you need, drop the old column and then rename the temp column with the original name.
If you have indexes on this column, you may want to bear in mind any impact this might have.

Convert table column data type from blob to raw

I have a table designed like,
create table tbl (
id number(5),
data blob
);
Its found that the column data have
very small size data, which can be stored in raw(200):
so the new table would be,
create table tbl (
id number(5),
data raw(200)
);
How can I migrate this table to new design without loosing the data in it.
This is a bit lengthy method, but it works if you are sure that your data column values don't go beyond 200 in length.
Create a table to hold the contents of tbl temporarily
create table tbl_temp as select * from tbl;
Rem -- Ensure that tbl_temp contains all the contents
select * from tbl_temp;
Rem -- Double verify by subtracting the contents
select * from tbl minus select * from tbl_temp;
Delete the contents in tbl
delete from tbl;
commit;
Drop column data
alter table tbl drop column data;
Create a column data with raw(200) type
alter table tbl add data raw(200);
Select & insert from the temporary table created
insert into tbl select id, dbms_lob.substr(data,200,1) from tbl_temp;
commit;
We are using substr method of dbms_lob package which returns raw type data. So, the resulted value can be directly inserted.