BLOB to String, SQL Server - sql

I have a text string stored as a BLOB data type in a database. I want to extract it by an SQL select query, but I have problems converting/casting from BLOB to readable text.
I've tried e.g.
select convert(nvarchar(40),convert(varbinary(40),BLOBTextToExtract))
from [NavisionSQL$Customer]
I guess I need something similar, but I can't figure out exactly what I need to do the conversion. Can somebody please give me some directions?
Regards

The accepted answer works for me only for the first 30 characters.
This works for me:
select convert(varchar(max), convert(varbinary(max),myBlobColumn)) FROM table_name

Problem was apparently not the SQL server, but the NAV system that updates the field. There is a compression property that can be used on BLOB fields in NAV, that is not a part of SQL Server. So the custom compression made the data unreadable, though the conversion worked.
The solution was to turn off compression through the Object Designer, Table Designer, Properties for the field (Shift+F4 on the field row).
After that the extraction of data can be made with e.g.:
select convert(varchar(max), cast(BLOBFIELD as binary))
from Table
Thanks for all answers that were correct in many ways!

It depends on how the data was initially put into the column. Try either of these as one should work:
SELECT CONVERT(NVarChar(40), BLOBTextToExtract)
FROM [NavisionSQL$Customer];
Or if it was just varchar...
SELECT CONVERT(VarChar(40), BLOBTextToExtract)
FROM [NavisionSQL$Customer];
I used this script to verify and test on SQL Server 2K8 R2:
DECLARE #blob VarBinary(MAX) = CONVERT(VarBinary(MAX), 'test');
-- show the binary representation
SELECT #blob;
-- this doesn't work
SELECT CONVERT(NVarChar(100), #blob);
-- but this does
SELECT CONVERT(VarChar(100), #blob);

Can you try this:
select convert(nvarchar(max),convert(varbinary(max),blob_column)) from table_name

Found this...
bcp "SELECT top 1 BlobText FROM TableName" queryout "C:\DesinationFolder\FileName.txt" -T -c'
If you need to know about different options of bcp flags...
http://msdn.microsoft.com/en-us/library/ms162802.aspx

CREATE OR REPLACE FUNCTION HASTANE.getXXXXX(p_rowid in rowid) return VARCHAR2
as
l_data long;
begin
select XXXXXX into l_data from XXXXX where rowid = p_rowid;
return substr( l_data, 1, 4000);
end getlabrapor1;

Related

SQL Server json truncated (even when using NVARCHAR(max) )

DECLARE #result NVARCHAR(max);
SET #result = (SELECT * FROM table
FOR JSON AUTO, ROOT('Data'))
SELECT #result;
This returns a json string of ~43000 characters, with some results truncated.
SET #result = (SELECT * FROM table
FOR JSON AUTO, ROOT('Data'))
This returns a json string of ~2000 characters. Is there any way to prevent any truncation? Even when dealing with some bigdata and the string is millions and millions of characters?
I didn't find and 'official' answer, but it seems that this is an error with the new 'FOR JSON' statement which is splitting the result in lines 2033 characters long.
As recommended here the best option so far is to iterate through the results concatenating the returned rows:
string result = "";
while (reader.Read())
{
result += Convert.ToString(reader[0]);
}
BTW, it seems that the latest versions of SSMS are already applying some kind of workaround like this to present the result in a single row.
I was able to get the full, non-truncated string by using print instead of select in SQL Server 2017 (version 14.0.2027):
DECLARE #result NVARCHAR(max);
SET #result = (SELECT * FROM table
FOR JSON AUTO, ROOT('Data'))
PRINT #result;
Another option would be to download and use Azure Data Studio which I think is a multi-platform re-write of SSMS (similar to how Visual Studio was re-written as VS Code). It seems to spit out the entire, non-truncated json string as expected out of the box!
This will also work if you insert into a temp table - not presenting does not apply the truncate of SSMS.
Might be usefull if you need to calculate several values.
declare #json table (j nvarchar(max));
insert into #json select * from(select* from Table where Criteria1 for json auto)a(j)
insert into #json select * from(select* from Table where Criteria2 for json auto)a(j)
select * from #json
I know this is an old thread but I have had success with this issue by sending the result to an XML variable. The advantage of using an XML variable is that the size is not stated as character length but by size of the string in memory, which can be changed in the options. Therefore Brad C's response would now look like...
DECLARE #result XML
SET #result = (SELECT * FROM table
FOR JSON AUTO, ROOT('Data'))
SELECT #result
or...
PRINT #result;
Here is the answer to JSON truncation:
SQL divides the JSON result into chunks 2k in size (at least my SQL 2016 installation does), one chunk in the first column of each row in the result set. To get the entire result, your client code has to loop through the result set and concatenate the first column of each record. When you've gotten to the end of the rows, voila, your entire JSON result is retrieved, uncut.
When I first encountered the truncation problem I was baffled, and wrote off FOR JSON for several years as an unserious feature suited only to the smallest of datasets. I learned that I need to read the entire recordset only from the FOR XML documentation, and never actually saw it mentioned in the FOR JSON docs.
The easiest workaround to avoid the truncation is to wrap the query in another select:
select (
<your query> FOR JSON PATH [or FOR JSON AUTO]
) as json
We've seen similar issues in SSMS, without using a variable SSMS truncates at 2033.
With a variable the query actually works OK when you use an nvarcahr(max) variable, but it truncates the output in the query results view at 43697.
A possible solution I've tested is outputting Query results to a file, using BCP:
bcp "DECLARE #result NVARCHAR(max); SET #result = (SELECT * FROM table FOR JSON AUTO, ROOT('Data')); SELECT #result as Result;" queryout "D:\tmp\exportOutput.txt" -S SQL_SERVER_NAME -T -w
See BCP docs for specifying server name\instance and authentication options
It's difficult to determine exactly what the problem you're having without posting the data, but I had a similar problem when I was attempting to export a query in JSON format. The solution that worked for me was to go to Query/Query Options/Results/Text/Set "Maximum number of characters displayed in each column:" to 8192 (max value AFAIK).
This probably won't help much with your first query, but that potentially could be broken into smaller queries and executed successfully. I would anticipate that you could effectively run your second query after changing that setting.
If your datalength is less than 65535 then you should use the suggestion of #dfundako who commented in the first post:
Try going to Tools, Options, Query Results, SQL Server, Results to Grid, and set Non-XML data to the max amount (I think 65535)
In my case the datalength was 21k characters so after exporting to grid I copied the value and it was fine, not truncated. Still it doesn't solve the the issue for those with bigger amount of data.
Try Visual Studio Code with Microsoft SQL extension. I got 6800 characters of JSON without truncation. It seems SSMS truncates results.

Convert HEX value to CHAR on DB2

In connection with data replication from SQL Server to DB2 I have the following question:
On DB2 I have a table containing (for simplicity) two columns: COL1 and COL2.
COL1 is defined as CHAR(20). COL2 is defined as CHAR(10).
COL1 is replicated from SQL by converting a string into hex, e.g. "abcdefghij" to "6162636465666768696A" or "1111111111" to "31313131313131313131" by using the following SQL query:
CONVERT(char(20), cast(#InputString as binary) 2)
where #InputString would be "abedefghij".
In other words COL1 contains the hex value, but as a string (sorry if the wording is incorrect).
I need to convert the hex value back to a string and put this value into COL2.
What should the SQL query be on DB2 to do the convertion? I know how to do this on SQL Server, but not on DB2.
Note: The reason the hex-value is not pre-fixed with "0x" is because style 2 is used in the CONVERT statement.
select hex('A') from sysibm.sysdummy1;
returns 41.
and
select x'41' from sysibm.sysdummy1;
gives you 'A'. So you can put that in a for loop and loop through each pair of hex characters to arrive at your original string. Or you can write your own unhex function.
Taken from dbforums.com /db2/1627076-display-hex-columns.html (edit Nov 2020: original source link is now a spam site)
DB2 has built-in encoding/decoding.
For OPs question, use....
select CAST(ColumnName as char(20) CCSID 37) as ColumnName from TableName where SomeConditionExists
http://www-01.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/com.ibm.db2z10.doc.intro/src/tpc/db2z_introcodepage.dita
This is one of most close topics to subject of my problem:
I have lost 2 days to figure out how to migrate XML files stored in DB2 BLOB field using SQL Developer.
(Yes, migrating to and doing the queries from SQL Developer - we are migrating data to Oracle from DB2, so we were using this tool)!
How to show XML file/string stored in BLOB?
Let's start with, what the problem was:
Data in BLOB was a XML file.
When selected in query, got:
When casted, like:
select CAST(BLOBCOLUMN as VARCHAR(1000)) from TABLE where id = 100;
output was in HEX:
Nothing worked... Not even the solution from the links in this topic.
!NOTHING!
By mistake found a solution:
CREATE FUNCTION in DB2:
CREATE FUNCTION unhex(in VARCHAR(32000) FOR BIT DATA)
RETURNS VARCHAR(32000)
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC NO EXTERNAL ACTION
BEGIN ATOMIC
RETURN in;
END
Run SELECT:
select UNHEX( CAST(BLOBCOLUMN as VARCHAR(32000) FOR BIT DATA)) from TABLE where id = 100;
Result:
I use this to convert FOR BIT DATA to characters:
cast (colvalue as varchar(2000) ccsid ebcdic for sbcs data)

SQL Server - Adding a string to a text column (concat equivalent)

How do you add a string to a column in SQL Server?
UPDATE [myTable] SET [myText]=' '+[myText]
That doesn't work:
The data types varchar and text are incompatible in the add operator.
You would use concat on MySQL, but how do you do it on SQL Server?
like said before best would be to set datatype of the column to nvarchar(max), but if that's not possible you can do the following using cast or convert:
-- create a test table
create table test (
a text
)
-- insert test value
insert into test (a) values ('this is a text')
-- the following does not work !!!
update test set a = a + ' and a new text added'
-- but this way it works:
update test set a = cast ( a as nvarchar(max)) + cast (' and a new text added' as nvarchar(max) )
-- test result
select * from test
-- column a contains:
this is a text and a new text added
Stop using the TEXT data type in SQL Server!
It's been deprecated since the 2005 version. Use VARCHAR(MAX) instead, if you need more than 8000 characters.
The TEXT data type doesn't support the normal string functions, while VARCHAR(MAX) does - your statement would work just fine, if you'd be using just VARCHAR types.
The + (String Concatenation) does not work on SQL Server for the image, ntext, or text data types.
In fact, image, ntext, and text are all deprecated.
ntext, text, and image data types will
be removed in a future version of
MicrosoftSQL Server. Avoid using these
data types in new development work,
and plan to modify applications that
currently use them. Use nvarchar(max),
varchar(max), and varbinary(max)
instead.
That said if you are using an older version of SQL Server than you want to use UPDATETEXT to perform your concatenation. Which Colin Stasiuk gives a good example of in his blog post String Concatenation on a text column (SQL 2000 vs SQL 2005+).
UPDATE test SET a = CONCAT(a, "more text")
hmm, try doing CAST(' ' AS TEXT) + [myText]
Although, i am not completely sure how this will pan out.
I also suggest against using the Text datatype, use varchar instead.
If that doesn't work, try ' ' + CAST ([myText] AS VARCHAR(255))
To Join two string in SQL Query use function CONCAT(Express1,Express2,...)
Like....
SELECT CODE, CONCAT(Rtrim(FName), " " , TRrim(LName)) as Title FROM MyTable

SQL Server - Replacing Single Quotes and Using IN

I am passing a comma-delimited list of values into a stored procedure. I need to execute a query to see if the ID of an entity is in the comma-delimited list. Unfortunately, I think I do not understand something.
When I execute the following stored procedure:
exec dbo.myStoredProcedure #myFilter=N'1, 2, 3, 4'
I receive the following error:
"Conversion failed when converting the varchar value '1, 2, 3, 4' to data type int."
My stored procedure is fairly basic. It looks like this:
CREATE PROCEDURE [dbo].[myStoredProcedure]
#myFilter nvarchar(512) = NULL
AS
SET NOCOUNT ON
BEGIN
-- Remove the quote marks so the filter will work with the "IN" statement
SELECT #myFilter = REPLACE(#myFilter, '''', '')
-- Execute the query
SELECT
t.ID,
t.Name
FROM
MyTable t
WHERE
t.ID IN (#myFilter)
ORDER BY
t.Name
END
How do I use a parameter in a SQL statement as described above? Thank you!
You could make function that takes your parameter, slipts it and returns table with all the numbers in it.
If your are working with lists or arrays in SQL Server, I recommend that you read Erland Sommarskogs wonderful stuff:
Arrays and Lists in SQL Server 2005
You need to split the string and dump it into a temp table. Then you join against the temp table.
There are many examples of this, here is one at random.
http://blogs.microsoft.co.il/blogs/itai/archive/2009/02/01/t-sql-split-function.aspx
Absent a split function, something like this:
CREATE PROCEDURE [dbo].[myStoredProcedure]
#myFilter varchar(512) = NULL -- don't use NVARCHAR for a list of INTs
AS
SET NOCOUNT ON
BEGIN
SELECT
t.ID,
t.Name
FROM
MyTable t
WHERE
CHARINDEX(','+CONVERT(VARCHAR,t.ID)+',',#myFilter) > 0
ORDER BY
t.Name
END
Performance will be poor. A table scan every time. Better to use a split function. See: http://www.sommarskog.se/arrays-in-sql.html
I would create a function that takes your comma delimited string and splits it and returns a single column table variable with each value in its own row. Select that column from the returned table in your IN statement.
I found a cute way of doing this - but it smells a bit.
declare #delimitedlist varchar(8000)
set #delimitedlist = '|1|2|33|11|3134|'
select * from mytable where #delimitedlist like '%|' + cast(id as varchar) + '|%'
So... this will return all records with an id equal to 1, 2, 33, 11, or 3134.
EDIT:
I would also add that this is not vulnerable to SQL injection (whereas dynamic SQL relies on your whitelisting/blacklisting techniques to ensure it isn't vulnerable). It might have a performance hit on large sets of data, but it works and it's secure.
I have a couple of blog posts on this as well, with a lot of interesting followup comments and dialog:
More on splitting lists
Processing list of integers

Accessing text fields in a stored procedure and insert to another table

I am trying to access a “text” type and inserting that value into another table viw a stored procedure. I’ve tried to cast it, convert it, but nothing works.
My code looks somethings like this:
Declare #Critique varchar(max), #Feedback varchar(max)
…
…
…
SELECT #Critique = CAST(comments as varchar(max)), #Feedback = CAST(public_critique as varchar(max)) FROM ASCO_vEXTERNAL_REVIEW_APPLICATIONS_LIST WHERE wf_task_assignment_id = #WfTaskAssignmentIDP1
– comments and public_critique are defined as text in view (also tried with table) ASCO_vEXTERNAL_REVIEW_APPLICATIONS_LIST
…
…
…
insert into WF_TASK_ASSIGNMENT_REVIEW (wf_task_assignment_review_id, wf_task_assignment_id, grantee_project_id, comments, public_critique) values (#NewID1, #WfTaskAssignmentIDP2, #GranteeProjectID, #Critique, #Feedback)
Can you please help me with this as soon as possible. I would really appreciate this.
Thanks,
Harish
I'm assuming that the WF_TASK_ASSIGNMENT_REVIEW is the one containing the text column you're trying to write into.
The text type is now deprecated in SQL 2005 and 2008. If at all possible try and upgrade the WF_TASK_ASSIGNMENT_REVIEW table to use the nvarchar(max) type instead.
If not, the only way is to use the WRITETEXT statement to write into the target column, in a loop (since WRITETEXT has an upper limit). See the WRITETEXT statement example in the SQL Server docs.
Your question is not sound good to understand .
Dont use text ,it wont support in many cases like where ,group by etc , so try use varchar
This is just an example
Declare #Critique varchar(max)
set #Critique = (select public_critique from ASCO_vEXTERNAL_REVIEW_APPLICATIONS_LIST
where convert(varchar(50), wf_task_assignment_id ) =#WfTaskAssignmentIDP1)