Insert data to specific field in internal table - abap

I have a table let's call it "dbtab".
The name of my internal table is "it_tab".
I have a number in "new_number".
I insert that number into the empty field "laufnr" in my dbtab by using:
update dbtab set laufnr = new_number where laufnr = ''.
This Works just fine, but the changes aren't in my it_tab.
How do I update my internal table from my dbtab?
Or how do I insert a value to a specific field in my internal table?

You have two options:
Update your internal table when you update the database table with something like: LOOP AT it_tab ASSIGING <tab> WHERE laufnr = ''. <tab>-laufnr = new_number. ENDLOOP.
Reread the data from the database table into your internal table after you have made the update to the database.

You could update your itab almost the same like a database table .. the only difference is, that you cannot use "update" ... use "modify" instead.
modify it_tab set laufnr = new_number where laufnr = '' .
An other option would be a simply reload of your dbtab
CLEAR it_tab.
SELECT * INTO it_tab FROM dbtab WHERE .... .

There are two different things, and they are not linked.
An internal table is a representation of a dataset in a specific moment in time.
A database table is the data itself up to date.
You can manage to change any of them, but not both at the same time with a single instruction.
I will reccomend to:
- update your database
- refresh the in-memory copy
TIP: if you want to do it "the hard way", just create an object, and do both things in some sort of UPDATE method.

hi try this hope it helps
LOOP AT it_tab.
it_tab-lufnr = new_number.
MODIFY it_tab TRASNPOTING laufnr WHERE laufnr = ''.
ENDLOOP.
or with conditions
LOOP AT it_tab where laufnr = ''.
it_tab-lufnr = new_number.
MODIFY it_tab TRASNPOTING laufnr WHERE laufnr = ''.
ENDLOOP.

Related

Stored Procedure to obtain part of the records name from a table?

Imagine that I have a table named "TableA" and this table has the columns "IDtable", "Tabname" and "Suffix".
IDtable and Tabname are correctly filled, but the suffix has all the records null.
I have to develop a stored procedure which allows to fill the Suffix column. For that, I know that I have to filter the name of the records in tabname.
Example:
Tabname: a_type_price
Suffix: price
Tabname: a_d_ser_sales
Suffix: sales
I think that I have to develop a for cycle, which looks for the " _ " in the names of Tabname and filters everything after the last " _ ".
Anyone have any idea of the best way to perform this stored procedure?
You'll want to update the table - you don't even really need a stored procedure unless this is something you ahve to run as a job or frequently.
You could do so like this:
CREATE PROCEDURE usp_Upd_TableASuffix()
AS
BEGIN
SET NOCOUNT ON
UPDATE TableA SET Suffix = RIGHT(Tabname, CHARINDEX('_', REVERSE(Tabname)) - 1)
END
Quick explanation of that: You want the RIGHT part of the string after the last _ character - to get the last one, use CHARINDEX on the REVERSE of the string.
You can't do this with a default constraint since you'd have to reference another column, but you could use a trigger, assuming IDtable is your primary key:
CREATE TRIGGER trg_TableA_Suffix
ON TableA
AFTER INSERT, UPDATE
AS
UPDATE TableA SET Suffix = RIGHT(i.Tabname, CHARINDEX('_',REVERSE(i.Tabname))-1)
FROM inserted i
WHERE TableA.IDTable = i.IDTable
GO
Note that this won't work if IDTable is non-unique, or if your table lacks a primary key entirely.
One last option - and this is probably the best if you really want Suffix to only ever contain the last part of Tabname and never want to change it - you could make Suffix a computed column.
ALTER TABLE TableA DROP COLUMN Suffix
ALTER TABLE TableA ADD Suffix AS RIGHT(Tabname, CHARINDEX('_',REVERSE(Tabname))-1) PERSISTED
For informix.
As #dan-field said, and explain, you can do the update using:
UPDATE tablea
SET suffix = RIGHT(tabname, CHARINDEX('_', REVERSE(tabname)) - 1);
Another way is:
UPDATE tablea
SET suffix = SUBSTR(tabname, INSTR(tabname, '_', -1)+1);
INSTR will give you the index of the first occurrence from the right (-1) of ''. SUBSTR will give you the substring starting from the index you pass, in this case we add 1 because we don't want the '' to be outputted.
Bear in mind that RIGHT, CHARINDEX, REVERSE and INSTR functions are only available from 11.70 onward.
On 11.50 you can try this ugly solution:
CREATE PROCEDURE test()
DEFINE i_IDtable LIKE tablea.IDtable;
DEFINE c_suffix LIKE tablea.tabname;
DEFINE i INT;
FOREACH cur1 WITH HOLD FOR
SELECT IDtable ,Tabname
INTO i_IDtable, c_suffix
FROM tablea
LET i = LENGTH(c_suffix);
WHILE i > 0
IF SUBSTR(c_suffix,i) LIKE '\_%' THEN
LET c_suffix = SUBSTR(c_suffix,i+1);
EXIT WHILE;
ELSE
LET i = i -1;
END IF
END WHILE;
UPDATE tablea
SET suffix = c_suffix,
WHERE idtable = i_IDtable;
END FOREACH;
END PROCEDURE;
But if suffix is always this part of the tabname it's not a good practice to store on the table.
You can easily get it from the already stored tabname. And even programmatically is easy to deal with it.

Creating a dynamic trigger comparing all fields in Firebird

For updating a field called 'last_modified' I'm trying to update this field automatically using a trigger, in stead of changing all update-statements. The field should only be updated when a field value has changed. Problem here is that you have to maintain the triggers if a table field is added, removed or renamed. The fields are stored in rdb$relation_fields, no problem. But building a query comparing the old and new value dynamically is.
create trigger test for test_table active before update position 0 as
declare variable fn char(31);
begin
for select rdb$field_name from rdb$relation_fields where rdb$relation_name = 'test_table' into :fn do
begin
if ('old.'||:fn <> 'new.'||:fn) then
begin
new.last_modified = current_timestamp;
break;
end
end
end
Problem here is that 'old.'||:fn and 'new.':fn not really are comparing values, but literal strings, so the value of the fields cannot be compared. I've seen over here Firebird - get all modified fields inside a trigger that a trigger is attached to a system table, something I don't want to.
Is this fully-automated way of updating the 'last_modified' field not possible in this way? Or do I have to create a stored procedure that deletes al triggers and then recreates them with new fields, once I perform a update on the database (using this code http://www.firebirdfaq.org/faq133/).

MS SQL use IDENT_CURRENT as variable of query

I need to use the IDENT_CURRENT of a specific table inside a query I'm writing.
I don't want to do a query to store the ID and another query to use it. I'd like something like:
UPDATE my_table1
SET my_column1 = IDENT_CURRENT(my_table2)
WHERE my_column2 = ?
Is it possible?
Yes, this code will work fine.
Table name for the function IDENT_CURRENT must be in quotas:
UPDATE my_table1
SET my_column1 = IDENT_CURRENT('my_table2')
WHERE my_column2 = ?
Needs quotes around table name.
UPDATE my_table1
SET my_column1 = IDENT_CURRENT('my_table2')
WHERE my_column2 = ?

Update or insert element into xml column dependent on existence

I'm trying to write an update statement that checks if an element exists in an XML column, and updating it's value if it exists. If not it will then insert the value as a new element.
Something like:
UPDATE Table
SET xmlCol =
case
when xmlCol.exist('element') = 1
then xmlCol.modify('replace value of blah')
else xmlCol.modify('insert blah')
end
where whatever
Am I going about this the wrong way?
The modify() method of the xml data type can only be used in the SET clause of an UPDATE statement.
It's probably simplest to do it in two statements.
UPDATE Table
SET xmlCol.modify('replace value of /blah')
WHERE xmlCol.exist('/blah') = 1;
UPDATE Table
SET xmlCol.modify('insert /blah')
WHERE xmlCol.exist('/blah') = 0;

SQL Trigger to update row

I need a SQL trigger that would zero pad a cell whenever its inserted or updated. Was curious if its best practice to append two strings together like I'm doing in the update command. Is this be best way to do it?
CREATE TRIGGER PadColumnTenCharsInserted ON Table
AFTER INSERT
AS
DECLARE
#pad_characters VARCHAR(10),
#target_column NVARCHAR(255)
SET #pad_characters = '0000000000'
SET #target_column = 'IndexField1'
IF UPDATE(IndexField1)
BEGIN
UPDATE Table
SET IndexField1 = RIGHT(#pad_characters + IndexField1, 10)
END
GO
Your padding code looks fine.
Instead of updating every row in the table like this:
UPDATE Table
update just the row that triggered the trigger:
UPDATE updated
Also, you've still got some extraneous code -- everything involving #target_column. And it looks like you're not sure if this is an INSERT trigger or an UPDATE trigger. I see AFTER INSERT and IF UPDATE.
Two questions:
What are you doing with #target_column? You declare it and set it with a column name, but then you never use it. If you intend to use the variable in your subsequent SQL statements, you may need to wrap the statements in an EXECUTE() or use sp_executesql().
The syntax "UPDATE Table..." is OK for your update statement assuming that "Table" is the name of the table you are updating. What seems to be missing is a filter of some kind. Or did you really intend for that column to be updated for every row in the whole table?
One way to handle this would be to declare another variable and set it with the PK of the row that is updated, then use a where clause to limit the update to just that row. Something like this:
DECLARE #id int
SELECT #id = Record_ID FROM INSERTED
-- body of your trigger here
WHERE Record_ID = #id
I like your padding code. It looks good to me.