1

I have a table City; my Pic column datatype is varbinary(max):

enter image description here

I update my pic column with this code and work (for 1 pic):

UPDATE City 
SET pic = 0xwed323422222222.... 
WHERE id = 4

but how can I update 3 images or more in Pic column? (add to existing image)

It my means I stored in table where id = 4 just 1 image binary. How can I save more than 1 image in a single column?

6
  • 2
    It might seem like a smart move to store multiple images in a single column - but DON'T DO THIS! You should never ever store multiple items into a single column - that's just asking for trouble and maintenance woes long term. Commented Jan 25, 2020 at 19:32
  • If I don't store multiple images in a single column,Some rows have 40 images and some have 3 and some have 10 . So I have to have 40 columns for storing images , and how do I know each rows how many images has to display? Commented Jan 25, 2020 at 20:13
  • 2
    You seem to have a design problem. A column of a row should hold one and only one attribute of the "thing" that is represented by the table. We don't know what your goal is with storing a picture (or multiple pictures) of a city, but the proper design to store multiple pictures for a city is to create a child table that has a foreign key to your city table. There is no "array" type in tsql and I think you are trying to apply concepts from other languages here inappropriately. Commented Jan 25, 2020 at 20:32
  • @smor i have 5000 City, if I create a child table for any city that Loads a heavy load to the server for upload or download pic by users. Commented Jan 25, 2020 at 20:42
  • 1
    You should use a proper, relational model : 1 city can be linked to n pictures in a separate table - one picture per row. That's the right way to go Commented Jan 25, 2020 at 21:40

1 Answer 1

1

You could store multiple images in a "semi-structured" way, within a single column by leveraging xml (and its structural integrity). You could change the datatype of the "pic" column to xml or keep it varbinary (some type casting is required for the latter).

The following example assumes varbinary storage for "the image" column and a "c:\testnew" folder (on the sql instance) which contains 3 images (image[1..3].png).

First, the two images are loaded for "the image" column of cityid=1 and later on the third image is appended to the binary data(first 2 pics) with update .write(). Removing images or inserting images in specific place within the blob could be achieved by utilizing the xml.modify() method.

All this, if you really need/have to store multiple images in a single row&column.

create table dbo.TestImages
(
    id int identity(1,1) constraint pkidTestImages primary key clustered(id),
    CityId int,
    ImagesBlobXml varbinary(max) --or xml
)
go


--insert two images from folder c:\testnew
insert into dbo.TestImages
(
    CityId, ImagesBlobXml
)

values (
1, 
cast((
select TheImage
from 
(
select *
from openrowset(bulk N'C:\testnew\image1.png', single_blob) as i(TheImage)
union all
select *
from openrowset(bulk N'C:\testnew\image2.png', single_blob) as i(TheImage)
--union all
--select *
--from openrowset(bulk N'C:\testnew\stackoverflow.png', single_blob) as i(TheImage)
) as images
for xml path(''), type
) as varbinary(max))
);

select 'table content', *
from  dbo.TestImages;


--retrieve images (2)
select 'images in blob, initial insert', t.id, t.CityId, i.bin.value('.', 'varbinary(max)') as TheImage
from
(
select *, cast(ImagesBlobXml as xml) as ImagesBlobXmlXML
from dbo.TestImages 
) as t
cross apply t.ImagesBlobXmlXML.nodes('TheImage') as i(bin);


--append new image
update t
set ImagesBlobXml .WRITE( --note:write cannot be used on NULL values
cast((
select TheImage
from 
(
select *
from openrowset(bulk N'C:\testnew\image3.png', single_blob) as i(TheImage)
) as images
for xml path(''), type
) as varbinary(max)) , 
null, 0 --write() append
)
from dbo.TestImages as t
where CityId = 1;


--retrieve the images (3)
select 'images in blob, after update_append', t.id, t.CityId, i.bin.value('.', 'varbinary(max)') as TheImage
from
(
select *, cast(ImagesBlobXml as xml) as ImagesBlobXmlXML
from dbo.TestImages 
) as t
cross apply t.ImagesBlobXmlXML.nodes('TheImage') as i(bin);

--check for any diff
select i.bin.value('.', 'varbinary(max)') as TheImage
from
(
select *, cast(ImagesBlobXml as xml) as ImagesBlobXmlXML
from dbo.TestImages 
) as t
cross apply t.ImagesBlobXmlXML.nodes('TheImage') as i(bin)
except
select TheImage
from 
(
select *
from openrowset(bulk N'C:\testnew\image1.png', single_blob) as i(TheImage)
union all
select *
from openrowset(bulk N'C:\testnew\image2.png', single_blob) as i(TheImage)
union all
select *
from openrowset(bulk N'C:\testnew\image3.png', single_blob) as i(TheImage)
) as images;
go

--cleanup
drop table dbo.TestImages;
go
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.