Why are the scalar variables undeclared inside cursor? - sql

I wrote a code snippet that is supposed to read a mapping table (BcwmWDConfig) and insert/update values of an outdated table (Items) in an old database (BCWM99) to a newer table in another database (WebDET99.dbo.Items).
I am getting errors that my supposedly declared (at least I thought so) variables are not declared.
DECLARE #v_bcwm_id INT = 0,
#v_wd_guid VARCHAR = '';
DECLARE bcwm_config_read_cursor CURSOR FOR
SELECT c.id, c.guid
FROM BcwmWDConfig c
WHERE c.guid IS NOT NULL;
PRINT '----READING CONFIG----';
OPEN bcwm_config_read_cursor
FETCH NEXT FROM bcwm_config_read_cursor INTO #v_bcwm_id, #v_wd_guid
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT '----READ CONFIG FOR ID: '+#v_bcwm_id+' AS GUID '+#v_wd_guid+'----'
PRINT '----INSERTING ITEMS WITH PARENT GUID: '+#v_wd_guid+'----'
INSERT INTO WebDET99.dbo.Items
SELECT
i.Id, i.Text,
CAST(#v_wd_guid AS VARCHAR(50)),
CAST(i.Linked_Feld AS VARCHAR(50)),
i.Linked_Item, i.Order
FROM
BCWM99.dbo.Items i
WHERE
i.Parent_Feld = #v_bcwm_id
PRINT '----INSERTED ITEMS WITH PARENT GUID: '+#v_wd_guid+'-----'
FETCH NEXT FROM bcwm_config_read_cursor INTO #v_bcwm_id, #v_wd_guid
END
CLOSE bcwm_config_read_cursor;
DEALLOCATE bcwm_config_read_cursor;
SET #v_bcwm_id = 0, #v_wd_guid = '';
OPEN bcwm_config_read_cursor
FETCH NEXT FROM bcwm_config_read_cursor
INTO #v_bcwm_id, #v_wd_guid
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT '----READ CONFIG FOR ID: '+#v_bcwm_id+' AS GUID '+#v_wd_guid+'----'
PRINT '----UPDATING ITEMS WITH LINKED FIELD: '+#v_wd_guid+'----'
UPDATE WebDET99.dbo.Items i
SET i.Linked_Feld = #v_wd_guid
WHERE i.Parent_Feld = CAST(#v_bcwm_id AS VARCHAR(50))
PRINT '----UPDATED ITEMS WITH LINKED FIELD: '+#v_wd_guid+'-----'
FETCH NEXT FROM bcwm_config_read_cursor
INTO #v_bcwm_id, #v_wd_guid
END
CLOSE bcwm_config_read_cursor;
DEALLOCATE bcwm_config_read_cursor;
SET #v_bcwm_id = 0,
#v_wd_guid = '';
Why are they undeclared inside the cursors? Also I am pretty sure I have some smaller syntax errors in my code, I am not used to SQL Server, maybe someone finds some other issues with this procedure.

Your code is sysntactically incorrect.
The first error: you cannot use Order (reserved word) without square brackets:
SELECT
i.Id, i.Text,
CAST(#v_wd_guid AS VARCHAR(50)),
CAST(i.Linked_Feld AS VARCHAR(50)),
i.Linked_Item, i.[Order] -----------------------------square brackets!
Second error:
SET #v_bcwm_id = 0, #v_wd_guid = '';
Should be:
SET #v_bcwm_id = 0; set #v_wd_guid = ''; ------------the same in the last row
The last error: get rid of "i":
UPDATE WebDET99.dbo.Items
SET Linked_Feld = #v_wd_guid
WHERE Parent_Feld = CAST(#v_bcwm_id AS VARCHAR(50))
Only then your code can be compiled.

Related

SQL smart search possible?

I am trying to pull a list from a large repository. And if there are spaces in this search, I separate the spaces and search separately. So far everything is working fine. And I am sending a list to the JS side to highlight the searched words. The word in the example search is 'paston'. I need to search for it as 'piston' or 'peston', is it possible? The only way I could think of was to change each letter of the words coming from the search in SQL to _ respectively and add them to the end with or, like '_iston' or 'p_ston' or 'pi_ton'. but I'm not sure if this works slow. Does anyone have any suggestions or know of a ready-made structure in SQL?
My SQL code is like this:
ALTER PROCEDURE [dbo].[GetStoklar]
#PageIndex nvarchar(15)
,#PageSize nvarchar(15)
,#Ara nvarchar(max)
AS
BEGIN
DECLARE #sql NVARCHAR(MAX);
DECLARE #NAME VARCHAR(100);
SET #sql = '
Select STOK_KODU,STOK_ADI,GRUP_KODU from TBLSTSABIT where 1=1'
DECLARE CUR CURSOR FOR
SELECT Deger FROM dbo.splitstring(''+#Ara+'')
OPEN CUR
FETCH NEXT FROM CUR INTO #NAME
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql=#sql+' AND STOK_ADI+STOK_KODU+GRUP_KODU LIKE ''%'+#NAME+'%'''
FETCH NEXT FROM CUR INTO #NAME
END
CLOSE CUR
DEALLOCATE CUR
SET #sql = #sql + ' order by STOK_KODU asc offset (CAST('+#PageIndex+' as int)*CAST('+#PageSize+' as int)) Rows fetch next CAST('+#PageSize+' as int) rows only
'
EXEC sp_executesql #sql;
PRINT #SQL;
RETURN
END
on the C# side like this
StringBuilder test = new StringBuilder();
JsonModel jsonmodel = new JsonModel();
if (Arama != "")
{
foreach (var item in Arama.Split(' '))
{
test.Append(item + "~");
}
}
test.Remove(test.ToString().Length - 1, 1);
jsonmodel.Filtre = test.ToString();
int pagesize = 15;
var tbrow = isStatic.GetStokListesi(pageindex, pagesize, Arama);
jsonmodel.NoMoredata = tbrow.Count < pagesize;
jsonmodel.HTMLString = isStatic.RenderToString(PartialView("_partial", tbrow));
return Json(jsonmodel);
This is the search function.
public static List<Stoklar> GetStokListesi(int pageindex, int pagesize, string Arama)
{
using (blabla db = new blabla())
{
return db.Database.SqlQuery<Stoklar>("[GetStoklar] #PageIndex,#PageSize,#Ara",
new SqlParameter("#PageIndex", pageindex.ToString()), new SqlParameter("#PageSize", pagesize.ToString()), new SqlParameter("#Ara", Arama)).ToList();
}
}
Is there a way to use this more meaningfully on the SQL side?
You can replace all single characters in a word by an '_', and then use these results in a LIKE
For replacing all single characters in a word, see: DBFIDDLE

Iterate over two loops (CURSOR and WHILE) and print the records grouped by location

I want to print the records grouped by each location (in this case they are 2), duly ordered.
I'm testing with a cursor but it prints the same location twice.
How can I fix this?
DECLARE #DateMovementsTopWorst AS DATE;
DECLARE #InventoryOnSiteTopWorst AS NUMERIC;
DECLARE #FamilyTopWorst AS VARCHAR(50)
DECLARE #BufferTopWorst AS NUMERIC;
DECLARE #SkuTopWorst AS VARCHAR(50);
DECLARE #LocationTopWorst AS VARCHAR(50);
DECLARE #Counter3 AS INT = 1;
DECLARE #Location AS VARCHAR(50);
DECLARE #Temporal2 AS INT = 10;
DECLARE ExternCursor CURSOR
FOR SELECT DISTINCT(LOCATION) FROM TFSCM_CLI_BUFFER
OPEN ExternCursor
FETCH NEXT FROM ExternCursor INTO #Location;
WHILE ##FETCH_STATUS = 0
--WHILE #Counter3 < #Temporal+1
BEGIN
DECLARE #Counter2 AS INT = 1;
--SET ROWCOUNT #Counter3;
PRINT ' SKU: '
+ ' Size: '
+ ' Family: '
+ ' Inventory: '
+ ' Movement Date: '
WHILE #Counter2 < 6
BEGIN
SET ROWCOUNT #Counter2;
SELECT #SkuTopWorst= SKU,
#BufferTopWorst= BUFFER,
#FamilyTopWorst = FAMILY,
#InventoryOnSiteTopWorst = TOTAL_INVENTORY_ON_SITE,
#DateMovementsTopWorst = UPDATE_MOVEMENTS,
#LocationTopWorst = LOCATION,
#Temporal2 = COUNT(*) OVER ()
FROM TFSCM_CLI_BUFFER
WHERE LOCATION = #Location
ORDER BY TOTAL_INVENTORY_ON_SITE ASC;
PRINT #SkuTopWorst
+ ' '
+ CONVERT(VARCHAR(100), #BufferTopWorst)
+ ' '
+ #FamilyTopWorst
+ ' '
+ CONVERT(VARCHAR(100), #InventoryOnSiteTopWorst)
+ ' '
+ CONVERT(VARCHAR(100), #DateMovementsTopWorst);
SET #Counter2 = #Counter2+1;
END
PRINT 'This is: ' + #Location;
--SET #Counter3 = #Counter3+1;
FETCH NEXT FROM ExternCursor;
END
CLOSE ExternCursor
DEALLOCATE ExternCursor
Edited with suggestions from users. But we have the same results
You're not using the cursor data for anything - therefore you inner query gets all your locations. You need to obtain the value from the cursor and then use it to filter your inner query. The following changes are required:
Add DECLARE #Location AS VARCHAR(50); near the start.
Modify your fetch's to be FETCH NEXT FROM ExternCursor INTO #Location;
Modify your inner where to be WHERE [LOCATION] = #Location
In the WHILE loop you have the SQL with this statement:
WHERE LOCATION IN (SELECT DISTINCT(LOCATION)
FROM TFSCM_CLI_BUFFER)
So the WHILE loop get all the location,
you need to change both:
FETCH NEXT FROM ExternCursor;
into
FETCH NEXT FROM ExternCursor INTO #location;
and then the WHERE statement in
WHERE LOCATION = #location
So for each Distinct location in TFSCM_CLI_BUFFER the WHILE loop will take care of one at a time.
P.S. Declare #location with the other var before the cursor.

Adding Trailing Zeros to an int field in SQL

In the process of resequencing my web items, I am trying to append 4 zeros on the end of each item sequence number. Everything I try does not work, it seems to automatically remove the trailing zeros because of formatting. This is an int field. The only thing I got to work for 1 item as a test was actually doing a replace such as:
update sacatalogitem
set itm_seq = replace(itm_seq, '8021', '80210000')
where itm_id = '13' and ctg_id = '917'
I have tried using a cursor with the replace and it strips the trailing zeros when executing this:
declare #SEQ int
declare #ID int
declare #CTG int
declare cur cursor for
select a.itm_seq, a.itm_id, a.ctg_id from sacatalogitem as a
join saitem as b on b.itm_id = a.itm_id
where a.cat_id = '307' and a.itm_id = '13' and a.ctg_id = '917'
open cur
fetch next from cur into #SEQ,#ID,#CTG
While (##FETCH_STATUS=0)
Begin
Update sacatalogitem
set itm_seq = replace(itm_seq, #SEQ, #SEQ + '0000')
where itm_id = #ID and ctg_id = #CTG
Update saitem
set itm_import_action = 'P'
where itm_id = #ID
fetch next from cur into #SEQ,#ID,#CTG
end
close cur
deallocate cur
This also fails for me:
update sacatalogitem
set itm_seq = itm_seq + '0000'
where itm_id = '13' and ctg_id = '917'
Any help would be appreciated for this small frustrating problem.
If it is an integer field, MULTIPY IT BY 10000.
update sacatalogitem
set itm_seq = itm_seq * 10000
where itm_id = '13' and ctg_id = '917'
You could try
cast(cast (itemsec as varchar) + '0000' as int)
but frankly #VJHill 's answer is neater

Code inside SQL Cursor will only execute first FETCH

I have a SQL Cursor which I'm having issues with. When I remove the IF #debug = 1 statement from inside the cursor, only the first record from the FETCH will get updated but if I leave the IF #debug = 1 all the required records are updated. Any idea as to why this is happening, I know most likely something is wrong with my Cursor? Code is below:
DECLARE Verify_Shipment_Cur CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
SELECT DISTINCT lpd_shipment_id, lpd_po_number, lpd_customer_id, lpd_sku, lpd_lottable01, lpd_lottable02, lpd_lottable03, lpd_putaway_zone, lpd_pdt
FROM PO_DETAIL01(NOLOCK)
WHERE lpd_shipment_id = #i_SHIPMENT_ID
AND lpd_po_number = #i_POKEY
AND lpd_customer_id = #i_CUSTOMER_ID
AND lpd_status = #AvailableStatus
OPEN Verify_Shipment_Cur
WHILE #ShipmentSKUCount >= #ShipmentSKUCountCur
BEGIN
FETCH NEXT FROM Verify_Shipment_Cur INTO #ShipmentID, #POKey, #CustomerID, #SKU, #Lottable01, #Lottable02, #Lottable03, #PutawayZone, #PDT
IF EXISTS(SELECT 1 FROM PO_DETAIL(NOLOCK) WHERE pd_asn_number = #i_SHIPMENT_ID AND pd_po_number = #i_POKEY
AND pd_sku = #SKU AND pd_type = #ShmtType AND pd_ordered_qty <> pd_received_qty)
BEGIN
UPDATE PO_DETAIL
SET pd_adjusted_qty = pd_ordered_qty - pd_received_qty
WHERE pd_asn_number = #i_SHIPMENT_ID
AND pd_po_number = #i_POKEY
AND pd_sku = #SKU
AND pd_type = #ShmtType
END
UPDATE PO_DETAIL
SET pd_lottable01 = #Lottable01
, pd_lottable02 = #Lottable02
, pd_lottable03 = #Lottable03
, pd_lottable04 = ''
, pd_lottable05 = #Date
, pd_putaway_zone = #PutawayZone
, pd_pdt = #PDT
, pd_status = #VerifiedStatus
WHERE pd_asn_number = #i_SHIPMENT_ID
AND pd_po_number = #i_POKEY
AND pd_sku = #SKU
AND pd_type = #ShmtType
UPDATE PO_DETAIL01
SET lpd_status = #VerifiedStatus
WHERE lpd_shipment_id = #i_SHIPMENT_ID
AND lpd_po_number = #i_POKEY
AND lpd_customer_id = #i_CUSTOMER_ID
AND lpd_status = #AvailableStatus
IF #debug = 1
BEGIN
SELECT #ShipmentSKUCount AS SKUCOUNT
, #ShipmentSKUCountCur AS SKUCOUNTCUR
, #SKU AS SKU
, #ShipmentID AS SHIPMENT
, #POKey AS POKEY
END
SET #ShipmentSKUCountCur = #ShipmentSKUCountCur + 1
END
CLOSE Verify_Shipment_Cur
DEALLOCATE Verify_Shipment_Cur
It looked ok to me but i obviously dont have your data to assist. Can I recommend putting a few print statements in various parts of your cursor. That way you can see how the code is actually flowing. It doesnt help but thats what I would do.
Please, can you try to define explicilty both variables: set #ShipmentSKUCount=[initial value],set #ShipmentSKUCountCur=[initial or constant value] and see what will happen?
Also, I found there is no checking for a ##FETCH_STATUS. It may also result into reading same row twice or more.
Please, give a feedback.

Replacing a string in a text field

I have a column in my database table which has lows of text and lows of rows. In the text, a url needs to be changed for every row. In each row the url can exist more than once.
Can I use the replace function to change all the urls in the text field in my database table without affecting the rest of the text in that same column?
Thanks
Use REPLACE()
UPDATE table SET text = REPLACE(text, 'from', 'to')
Make precise from: like with http://url_from.com/ to http://url_to.com/
Based on article posted at https://web.archive.org/web/20150521050102/http://sqlserver2000.databases.aspfaq.com:80/how-do-i-handle-replace-within-an-ntext-column-in-sql-server.html
I needed to write a find and replace for CHAR(146) ` in a text field. Above article for fort nText and the same solution for text worked with nText with the following changes:
- VARCHAR(32) from nVARCHAR(32)
- use #lenOldString = DATALENGTH(#oldString) instead of SET #lenOldString = DATALENGTH(#oldString)/2.
DECLARE
#TextPointer BINARY(16),
#TextIndex INT,
#oldString VARCHAR(32),
#newString VARCHAR(32),
#lenOldString INT,
#currentDataID INT;
SET #oldString = '’';
SET #newString = '''';
IF CHARINDEX(#oldString, #newString) > 0
BEGIN
PRINT 'Quitting to avoid infinite loop.';
END
ELSE
BEGIN
--Need the for nText fields
--SET #lenOldString = DATALENGTH(#oldString)/2
--Use this for text fields
SET #lenOldString = DATALENGTH(#oldString)
DECLARE irows CURSOR
LOCAL FORWARD_ONLY STATIC READ_ONLY FOR
SELECT
DataID
FROM
dbo.tbData
WHERE
PATINDEX('%'+#oldString+'%', TextData) > 0;
OPEN irows;
FETCH NEXT FROM irows INTO #currentDataID;
WHILE (##FETCH_STATUS = 0)
BEGIN
SELECT
#TextPointer = TEXTPTR(TextData),
#TextIndex = PATINDEX('%'+#oldString+'%', TextData)
FROM
dbo.tbData
WHERE
DataID = #currentDataID;
SELECT #TextPointer, #TextIndex
WHILE
(
SELECT
PATINDEX('%'+#oldString+'%', TextData)
FROM
dbo.tbData
WHERE
DataID = #currentDataID
) > 0
BEGIN
SELECT
#TextIndex = PATINDEX('%'+#oldString+'%', TextData)-1
FROM
dbo.tbData
WHERE
DataID = #currentDataID;
UPDATETEXT dbo.tbData.TextData #TextPointer #TextIndex #lenOldString #newString;
END
FETCH NEXT FROM irows INTO #currentDataID;
END
CLOSE irows;
DEALLOCATE irows;
END