I have a stored procedure like the following:
declare #mySymbol as varchar(32)
DECLARE #RefGroupID AS VARCHAR(20)
declare #myJID as varchar(45)
declare Div_csr cursor for
select distinct Symbol2, RefGroupID, jnl_id
from #TDRows td
WHERE TD_CompanyCode_AU = 'A'
open Div_csr
fetch next from Div_csr into #mySymbol, #RefGroupID, #myJID
while ##FETCH_STATUS = 0 begin
SET #InfoMessage = #InfoMessage +CONVERT(varchar(30),getdate(), 120)+ ' ' + #SPname
+ ': RefGroupID:'+ convert(varchar(20),#RefGroupID,101)
+ ' Sym: ' + #mySymbol
+ ' JID: ' + #myJID
+ CHAR(13) + CHAR(10)
fetch next from Div_csr into #mySymbol, #RefGroupID, #myJID
end
close Div_csr
deallocate Div_csr
#mySymbol is the data I want to modified.
For example; #mySymbol is BXP PRB. You can see there is a space between BXP and PRB. I want to this space also show in the comment that was created using the stored procedure.
Right now, the commment's Sym: is parsed by data #mySymbol. But it does not have space now. I do not know why.. .
The comment looks like this:
"DIV2PAY Record receipt from CSH RecordDt=08/04/2017 Intended PayDt= 08/15/2017 Sym=BXPPRB Qty=-100 CashRate=0.328125 Kind= Cash Dividend RowID= 127278 CAEventID= 105226767
".
Could anyone help me with this?
Related
I would like to store large images in SQL Server and later use them in Reporting Services, Power BI and Analysis Services.
I found some help, but I still don't understand what is the best way to store them and how to convert these images in the correct format.
Should I convert them to Base64? How do I do that?
I found good explanations on Convert Image DataType To String in SQL Server, Storing images in SQL Server?, but none of them worked with me.
So I have on my database, the path of the image, the image it self and the extension as below:
SELECT
NM_DIRETORIO AS NM_PATH ,
NM_FOTO AS NM_PICTURE,
TP_EXTENSAO AS TP_EXTENSION
FROM D_GB_FOTOS
As I saw it on from this video SSRS - Read images from the SQL Server database, he uses varbinary(max) to store images, but I don't how he converted to that. Also, from Chriss Webb's: Storing Large Images In Power BI Datasets, he uses Base64 to show on Power BI.
So my question is, since I'll use large images, how to I convert a simple image (path + picture) to store in my SQL Server database?
Information:
SQL Server 2019 (v15.0.18330.0)
SQL Server Management Objects (SMO) v16.100.37971.0
Microsoft SQL Server Management Studio v18.5
EDIT:
Based on #Peter Schneider answer, I have created a cursor for updating the table, with that value. But I got error on the where clause (e.g: TABLE.ID_COLUMN).
My cursor:
DECLARE #ID_FOTO INT;
DECLARE #CD_ARQUIVO VARCHAR(4000);
DECLARE #CD_ARQUIVO_VARBINARY VARCHAR(4000);
DECLARE #tsql NVARCHAR (4000);
DECLARE CUR CURSOR FOR SELECT ID_FOTO, CD_ARQUIVO, NM_DIRETORIO + '\' + NM_FOTO + TP_EXTENSAO AS CD_ARQUIVO_VARBINARY FROM D_GB_FOTOS WHERE LINORIGEM <> 'CARGA MANUAL'
OPEN CUR
FETCH NEXT FROM CUR INTO #ID_FOTO, #CD_ARQUIVO, #CD_ARQUIVO_VARBINARY
WHILE #CD_ARQUIVO IS NULL BEGIN
SET #tsql = 'UPDATE D_GB_FOTOS' +
'SET CD_ARQUIVO = (SELECT CD_ARQUIVO.* from Openrowset(Bulk' + #CD_ARQUIVO + ', Single_Blob) CD_ARQUIVO)' +
'WHERE ' + #ID_FOTO + ' = D_GB_FOTOS.ID_FOTO;'
PRINT (#tsql)
EXEC (#tsql)
FETCH NEXT FROM cur INTO #ID_FOTO, #CD_ARQUIVO
END
CLOSE cur
DEALLOCATE cur
EDIT 2:
Some adjustments to the query, but there is one final problem where it keeps updating, and doesn't stop with the final ID of the table:
DECLARE #ID_FOTO INT;
DECLARE #CD_ARQUIVO VARCHAR(4000);
DECLARE #CD_ARQUIVO_VARBINARY VARCHAR(4000);
DECLARE #tsql NVARCHAR (4000);
DECLARE #ID_FOTO_MAX INT;
SET #ID_FOTO_MAX = (SELECT MAX(ID_FOTO) AS ID_FOTO FROM D_GB_FOTOS);
DECLARE CUR CURSOR FOR SELECT ID_FOTO, CD_ARQUIVO, (NM_DIRETORIO + '\' + NM_FOTO + TP_EXTENSAO) AS CD_ARQUIVO_VARBINARY FROM D_GB_FOTOS WHERE LINORIGEM <> 'CARGA MANUAL';
OPEN CUR
FETCH NEXT FROM CUR INTO #ID_FOTO, #CD_ARQUIVO, #CD_ARQUIVO_VARBINARY
WHILE (#ID_FOTO <= #ID_FOTO_MAX) BEGIN
SET #tsql = 'UPDATE D_GB_FOTOS ' +
'SET CD_ARQUIVO = (SELECT CD_ARQUIVO from Openrowset(Bulk ''' + #CD_ARQUIVO_VARBINARY + ''', Single_Blob) CD_ARQUIVO)' +
' WHERE D_GB_FOTOS.ID_FOTO = ' + CONVERT(VARCHAR(10),#ID_FOTO) + ';'
PRINT ('ID_FOTO: ' + CONVERT(VARCHAR(10),#ID_FOTO))
PRINT ('ID_FOTO_MAX: ' + CONVERT(VARCHAR(10),#ID_FOTO_MAX))
PRINT ('SELECT STATEMENT: ' + #tsql)
EXEC (#tsql)
FETCH NEXT FROM cur INTO #ID_FOTO, #CD_ARQUIVO, #CD_ARQUIVO_VARBINARY
END
CLOSE cur
DEALLOCATE cur
Example from where I printed the code above:
(1 linha afetada) ID_FOTO: 6529 ID_FOTO_MAX: 6531
(1 linha afetada) ID_FOTO: 6530 ID_FOTO_MAX: 6531
(1 linha afetada) ID_FOTO: 6531 ID_FOTO_MAX: 6531
(1 linha afetada) ID_FOTO: 6531 ID_FOTO_MAX: 6531
(1 linha afetada) ID_FOTO: 6531 ID_FOTO_MAX: 6531
You can use OpenRowSet to read the image from disk and insert it into your table
INSERT INTO YourTableName (ID, VarbinaryMaxColumn) VALUES (1,
(SELECT * FROM OPENROWSET(BULK N'C:\Temp\Testimage.png', SINGLE_BLOB) AS VarbinaryMaxColumn)
)
'Trigger' I want to give information according to the profession using. For example; When I entered the engineer I added 'engineer'. This is his name and surname. ' as.
ALTER TRIGGER tigger_example
ON information
AFTER INSERT
AS
IF EXISTS(SELECT * FROM inserted WHERE Person_Job='Engineer')
BEGIN
PRINT 'Engineer added to list.'+
'Person Info:' +
'Name : ' + person_firstname + -- not work
'Surname : ' + person_lastname -- not work
END
ELSE IF EXISTS(SELECT * FROM inserted WHERE Person_Job='Architect')
BEGIN
PRINT 'Architect added to list.'+
'Person Info:' +
'Name : ' + person_firstname + -- not work
'Surname : ' + person_lastname -- not work
END
ELSE
BEGIN
PRINT 'An undefined contact has been added to the list.'
END
ERROR:
The name "person_firstname" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables. Column names are not permitted.
You have to use "SELECT ... from inserted" for read field value.
example:
ALTER TRIGGER tigger_example
ON information
AFTER INSERT
AS
DECLARE #MSG NVARCHAR(MAX)
IF EXISTS(SELECT * FROM inserted WHERE Person_Job='Engineer')
BEGIN
SET #MSG ='Engineer added to list.'+CHAR(13)+CHAR(10)+'Person Info:'
SELECT #MSG=#MSG+CHAR(13)+CHAR(10)+'Name : ' + person_firstname + 'Surname : ' + person_lastname
FROM inserted WHERE Person_Job='Engineer'
print #MSG
END
ELSE IF EXISTS(SELECT * FROM inserted WHERE Person_Job='Architect')
BEGIN
SET #MSG ='Architect added to list.'+CHAR(13)+CHAR(10)+'Person Info:'
SELECT #MSG=#MSG+CHAR(13)+CHAR(10)+'Name : ' + person_firstname + 'Surname : ' + person_lastname
FROM inserted WHERE Person_Job='Architect'
print #MSG
END
ELSE
BEGIN
PRINT 'An undefined contact has been added to the list.'
END
I am trying to replace a bunch of difficult to decipher abbreviations with corresponding detailed descriptions. I have a table called Abbreviations that simply holds a list of abbreviations to look for and the corresponding descriptions they should be changed to. Additionally the "Replaced" table holds a list of unaltered abbreviated descriptions that I would like to change in a single column called "DescriptionCodes"
The data I am trying to change is a list of different teas. For instance the entry
"TADIN H-B GR" would be the abbreviation for "TADIN HERBAL BAG GREEN"
The SQL Code I am currently using looks like this:
BEGIN TRANSACTION
DECLARE #Desc varchar(500)
DECLARE #Abbr varchar(500)
DECLARE contact_cursor CURSOR FOR
SELECT Description, Abbrv FROM dbo.Abbreviations
OPEN contact_cursor
FETCH NEXT FROM contact_cursor
INTO #Desc, #Abbr
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT 'Changing ' + #Abbr + ' to ' + #Desc
UPDATE Replaced
SET DescriptionCodes = REPLACE(DescriptionCodes, #Abbr, #Desc)
WHERE DescriptionCodes LIKE CONCAT('% ', #Abbr, ' %')
FETCH NEXT FROM contact_cursor
INTO #Desc, #Abbr
END
CLOSE contact_cursor
DEALLOCATE contact_cursor
COMMIT
Of course the problem I am running into is that once an abbreviation is applied the detailed description may contain a substring that matches another abbreviation that is then applied. For instance PKG might be changed to PACKAGE but PA is the abbreviation for PINEAPPLE as well, meaning that once that change is applied the final result would be PINEAPPLECKAGE. Every abbreviation has a single blank space on either side so I thought to use that fact to not update any abbreviation without a blank space on either side, hence the
CONCAT('% ', #Abbr, ' %') in my code. However, when I try this method basically nothing gets changed at all. I've been able to see limited success by removing that constraint but the other issue then happens. Any ideas as to how I could make sure that only occurrences of abbreviations with a blank space on either side are considered and updated?
UPDATE:
After trying several of the solutions posted here, I still haven't been able to get it to work and I'm not sure why. By all appearances this is correct. Here is a sample of some of the data I'm working with:
JUSTEA HBL PKG CMCL CHM LG LR 1.5OZ
PRIDE OF INDIA BG ASM B BKFST 25 CT
CTL BR H-B 7BLSM PP 1 CT
POSTI H-B HRH CRN 20 CT
DRS H-B EPGP LPLDS PTVP TGN 20 CT
ULTLC BG CHG 100 CT
PG TIPS BG D B 40 CT
RPBL R-B B HLDY FT BLD 6 CT
This is fine and looks like it should convert with no issues. Yet when I run the code with spaces indicated (As with "LIKE '% ' + #Abbr + ' %'", which was my first inclination) the data remains completely unchanged. If I remove them the data becomes completely unintelligible. For example the line beginning with PRIDE OF INDIA becomes
PRIDE OF INDIA(N) IRISH AFTERNOON BLACK AG ASIA PLUM RICOT SPICE(D) EARMINT BLACK BLACK KFST 25 CURRANT AN AID N T
I feel I should note that this data was imported from Excel Spreadsheets originally. Is there any chance that has anything to do with the spaces not being recognized?
Why use "LIKE" if you're going to add the spaces? just do:
WHERE DescriptionCodes = #Abbr
You can do this and it will achieve what you are trying to do:
LIKE '% ' + #Abbr + ' %'
I think you need to update each record of the Replaced table multiple times, and you need to consider the 4 locations of the abbreviations (Alone, First, In the middle, Last). Something like this:
DECLARE #Replaced TABLE ([DescriptionCodes] varchar(50))
DECLARE #Abbreviations TABLE ([Abbrv] varchar(50), [Description] varchar(50))
INSERT INTO #Replaced([DescriptionCodes]) VALUES ('TADIN H-B GR')
INSERT INTO #Replaced([DescriptionCodes]) VALUES ('PKG')
INSERT INTO #Replaced([DescriptionCodes]) VALUES ('PKG PA')
INSERT INTO #Abbreviations([Abbrv], [Description]) VALUES ('H-B', 'HERBAL BAG')
INSERT INTO #Abbreviations([Abbrv], [Description]) VALUES ('GR', 'GREEN')
INSERT INTO #Abbreviations([Abbrv], [Description]) VALUES ('PKG', 'PACKAGE')
INSERT INTO #Abbreviations([Abbrv], [Description]) VALUES ('PA', 'PINAPPLE')
DECLARE #RowCount int;
WHILE 1 = 1
BEGIN
SET #RowCount = 0;
UPDATE r
SET r.[DescriptionCodes] = REPLACE(r.[DescriptionCodes], a.[Abbrv], a.[Description])
FROM #Replaced r join #Abbreviations a ON r.[DescriptionCodes] = a.[Abbrv];
SET #RowCount = #RowCount + ##RowCount;
UPDATE r
SET r.[DescriptionCodes] = REPLACE(r.[DescriptionCodes], ' ' + a.[Abbrv] + ' ', ' ' + a.[Description] + ' ')
FROM #Replaced r join #Abbreviations a ON r.[DescriptionCodes] like '% ' + a.[Abbrv] + ' %';
SET #RowCount = #RowCount + ##RowCount;
UPDATE r
SET r.[DescriptionCodes] = REPLACE(r.[DescriptionCodes], ' ' + a.[Abbrv],' ' + a.[Description])
FROM #Replaced r join #Abbreviations a ON r.[DescriptionCodes] like '% ' + a.[Abbrv];
SET #RowCount = #RowCount + ##RowCount;
UPDATE r
SET r.[DescriptionCodes] = REPLACE(r.[DescriptionCodes], a.[Abbrv] + ' ', a.[Description] + ' ')
FROM #Replaced r join #Abbreviations a ON r.[DescriptionCodes] like a.[Abbrv] + ' %';
SET #RowCount = #RowCount + ##RowCount;
IF #ROWCOUNT = 0 BREAK;
END
SELECT * FROM #Replaced
I just face a problem while working on a stored procedure,
My situation is as below,
I'm calling a stored procedure inside another stored procedure like for example,
EXEC [SP_ADMIN_INSERT_ITEM_STOCK_DETAILS]
#stk_tran_no = #cash_purchase_no,
#stk_tran_date = GetDate(),
#tran_type = 'Cash Purchase',
#item_code = #item_code,
#quantity = #quantity
Currently in the above code we are passing current date to the parameter #stk_tran_date.
But now I need to pass date to #stk_tran_date by fetching that from some other table like,
select #stk_tran_date = Convert(datetime,cash_purchase_date,103) from Cash_Purchase_14 where cash_purchase_no = 'GOH-9/2014'
If you observe my table name is like Cash_Purchase_14 where 14 is a dynamic value which changes every year, as this is 2014 financial year so it looks like Cash_Purchase_14, next year it will be Cash_Purchase_15.
Because of this i use to write these quires first as string then I'll execute them as shown below,
declare #SQL nvarchar(4000)
set #SQL =N' Declare #cash_purchase_date1 datetime
set #cash_purchase_date1 = (select cash_purchase_date from Cash_Purchase_'+ #Financialyearpart +' where cash_purchase_no = ''' + #cash_purchase_no + ''')
print #cash_purchase_date1'
exec executesql #SQL
But I need the value of the variable #cash_purchase_date1 outside this block like below,
EXEC [SP_ADMIN_INSERT_ITEM_STOCK_DETAILS]
#stk_tran_no = #cash_purchase_no,
#stk_tran_date = #cash_purchase_date1,
#tran_type = 'Cash Purchase',
#item_code = #item_code,
#quantity = #quantity
but it is giving an error like, "declare the variable #cash_purchase_date1"
In Other case i tried like calling the stored procedure in side the string like,
SET #SQL =' Declare #cash_purchase_date1 datetime
set #cash_purchase_date1 = (select cash_purchase_date from Cash_Purchase_'+ #Financialyearpart +' where cash_purchase_no = ' + #qt + #cash_purchase_no + #qt +')
print #cash_purchase_date1
EXEC [SP_ADMIN_INSERT_ITEM_STOCK_DETAILS]
#stk_tran_no = ' + #qt + #cash_purchase_no + #qt +',
#stk_tran_date = #cash_purchase_date1,
#tran_type = ''Cash Purchase'',
#item_code = ' + #qt + #item_code + #qt +',
#quantity = ' + #quantity
exec executesql #SQL
In this scenario the value of #cash_purchase_date1 is not replacing it simply retains the same.
Please help to get the value of the variable outside the block.
Or
How can I append the value 14 at the end of the table name dynamically using a variable.
I Tried like
Declare #cash_purchase_date1 datetime
set #cash_purchase_date1 = cash_purchase_date from Cash_Purchase_+ #Financialyearpart
I think i made the problem bit complicated while explaining. Please help me in solving the issue.
Thanks in advance.
You can return values from dynamic sql by using sp_executesql with an output variable:
declare #SQL nvarchar(4000);
declare #cash_purchase_date datetime;
set #SQL = N'select #cash_purchase_date = cash_purchase_date from Cash_Purchase_' + #Financialyearpart + ' where cash_purchase_no = ''' + #cash_purchase_no + '''';
exec sp_executesql #SQL, N'#cash_purchase_date datetime OUTPUT', #cash_purchase_date = #cash_purchase_date OUTPUT;
I think this will solve your problem.
I am looping through all my databases and aggregating the results into an aggregates database.
In my loop I call
master.dbo.xp_cmdshell osql C:\whatever.SQL
As the loop progresses, the cmdshell takes longer and longer to execute. If I stop the loop and run a single aggregate for one database it executes quickly.
Is there anything I can add to my external SQL script to make it run faster? Maybe something to commit and free the records before the next loop? Or should I add some kind of a pause after every loop?
I want to use an external SQL file because it contains many update statements and it's more manageable for me.
Here's how I loop:
Update dbFoo.dbo.tblBar set Processed = 0
Go
WHILE EXISTS ( SELECT ID FROM dbFoo.dbo.tblBar WHERE Processed = 0)
BEGIN
SELECT #aRow = MIN(tblBar.ID) FROM dbFoo.dbo.tblBar
SELECT #aFoo1 = Foo1 FROM dbFoo.dbo.tblBar WHERE ID = #aRow
SELECT #aFoo2 = Foo2 FROM dbFoo.dbo.tblBar WHERE ID = #aRow
SELECT #aFoo3 = Foo3 FROM dbFoo.dbo.tblWhatever WHERE Foo = #aFoo
EXEC RunPreAgg #Foo1 = #aFoo1, #Foo2 = #aFoo2, #Foo3 = #aFoo3, #RetVal = #aRetVal OUTPUT
SELECT returning = #aRetVal
UPDATE dbFoo.dbo.tblBar SET Processed = 1 WHERE ID = #aRow
END
Then the RunPreAgg stored procedure basically does this:
if db_id('db' + #Foo1 + '_' + #Foo2) is not null
BEGIN
--This bat file creates the SQL File
select #sql = 'master.dbo.xp_cmdshell '''+#path+'wwwRunPreAgg.bat ' + #Foo1 + ' ' + #Foo2 + ' ' + #Foo3 + ''''
exec( #sql )
--execute
select #sql = 'master.dbo.xp_cmdshell ''osql -E -o '+#path+'output\tmp'+#Foo1+'_'+#Foo2+'.txt -i '+#path+'tmp' + #Foo1 + '.SQL'''
exec( #sql )
--This erases the SQL File
select #sql = 'master.dbo.xp_cmdshell '''+#path+'wwwCleanup.bat ' + #Foo1 + ' ' + #Foo2 + ''''
exec( #sql )
Set #retval = 'Done!'
END
ELSE
BEGIN
Set #retval = 'Err: No DataBase'
END
The variable names are changed to protect the innocent. The code works fine, I just need to optimize.
If it is the loops performance that is causing you trouble, you might try reducing the number of selects. Normally I dislike Cursors, but your loop might benefit from one. You can select all the values you need for the loop into memory, then loop through those values without having to run 3 or 4 selects per loop (of course if the performance hit is occurring inside the RunPreAgg SP, then this won't help):
DECLARE cFoos CURSOR FOR
SELECT tblBar.ID, tblBar.Foo1, tblBar.Foo2, tblWhatever.Foo3
FROM dbFoo.dbo.tblBar
INNER JOIN dbFoo.dbo.tblWhatever
ON tblWhatever.Foo = tblBar.Foo
WHERE tblBar.Processed = 0;
OPEN cFoos;
FETCH NEXT FROM cFoos INTO #aRow, #aFoo1, #aFoo2, #aFoo3;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC RunPreAgg #Foo1 = #aFoo1, #Foo2 = #aFoo2, #Foo3 = #aFoo3, #RetVal = #aRetVal OUTPUT
SELECT returning = #aRetVal
UPDATE dbFoo.dbo.tblBar SET Processed = 1 WHERE ID = #aRow
FETCH NEXT FROM cFoos INTO #aRow, #Foo1, #Foo2, #Foo3;
END
CLOSE cFoos;
DEALLOCATE cFoos;