FreePascal : ValueListEditor manipulation - freepascal

I have a Valuelisteditor that looks like this
Key | Name |
---------------|
Car | Audi |
Nick | Yummi |
Age | 70 |
and I want to modify the key "Nick" in Row 2 and keep the Name "Yummi".
I do not want to rewrite the whole row.
I just want to change "Nick" in "Nickname".
How can I do this in one strike?

Find the row you want to change, and then update the appropriate Cell:
var
iRow: Integer;
begin
// Find the row containing 'Nick' as the key
ValueListEditor1.FindRow('Nick', iRow);
// If it was found, update the key value (column 0 of the row)
if iRow > -1 then
ValueListEditor1.Cells[0, iRow] := 'NewNick';
end;
Note that TValueListEditor.Cells are 0 based, where the columns are Keys (column 0) and Values (column 1).

Related

mysql On Duplicate value in field, insert new row with new value

I want to add a new record in a table if duplicate value enters in a unique field. I don't want to update the existing one but want to add a new record by modifying the unique field value.
Is this possible in mysql?
EDIT:
Edited after user comment on this post:
You need write table locking on both of those two processes.
A WRITE lock has the following features:
The only session that holds the lock of a table can read and write data from the table.
Other sessions cannot read data from and write data to the table until the WRITE lock is released.
Also look at SQL UNIQUE Constraint
BEFORE EDIT:
Yes it is possible. And it took me awhile to figure it out. I build this on your input and compering values as test1, test2 etc, where test is always the same and has trailing number. As you specified.
It can be done as MySQL TRANSACTION in 4 steps.
Lets say you have table testT where name is unique to insure we have no doubles.
| id | name |
| --- | ----- |
| 1 | test1 |
| 2 | test3 |
And you want to insert a new item with name test1 we set is as:
SET #newName = 'test1';
Then we need to check if it already exists in table:
SELECT #check:=COUNT(*) FROM testT WHERE name = #newName;
We do a count here to get true or false and save it as #check here so we can compare it later. This will result into 1 row as test1 already exists in table.
Next we do another selection to get the highest number of test* and store it as #number, this next query selects all tests and does a SUBSTRING after 4 latter's giving us all numbers after first 4 latter's. (99999999999) numbers actually just to be sure we don't miss any but in our case result is only "3" because that is last record "test3" in table.
SELECT
#number:= SUBSTRING(name,5,99999999999)
FROM testT;
Now we can do an insert:
INSERT INTO testT(name)
VALUES
(
IF(#check = "", #newName , CONCAT(LEFT(#newName,4),RIGHT(#number,1)+1)
)
);
This tries to insert our #newName into table under IF condition, and that is if our #check is empty then he will insert #newName, if not it will take word test out of string and append a highest #number from earlier and add + 1 too it.
So result for #newName = 'test1' is below. If you change this into #newName = 'test3' result wold be same new insert test4.
**Schema (MySQL v5.7)**
SET #newName = 'test1';
---
**Query #1**
SELECT * FROM testT
ORDER BY id;
| id | name |
| --- | ----- |
| 1 | test1 |
| 2 | test3 |
| 3 | test4 |
---
And if you change it in ANY test* that number does not already exists it will insert it normally. In case below: #newName = 'test6'
SET #newName = 'test6';
**Query #1**
SELECT * FROM testT
ORDER BY id;
| id | name |
| --- | ----- |
| 1 | test1 |
| 2 | test3 |
| 3 | test6 |
This way an insert will always be made.
You can play with this here : View on DB Fiddle just by changing SET #newName = 'test6'
I am no expert and it took me couple of hours to figure this way out, as I wanted to know if this was even possible.
And I would appreciate if any other user can suggestion any other way or improve my method.

Creating Primary key from 2 autonumber and constant letter when creating table

I am new to MYSQL and would like to create a table where a constant Letter depicting the department is added to an auto increment number. This way I would be able to identify the category of the worker upon viewing the ID.
Ex. Dept A and employee 135. The ID I am imaging should read A135 or something similar. I have created the table, the auto increment works fine, the constant letter has been declared and is featuring. However I would like to concatenate them in order to use the A135 as a primary key.
Any Help Please?
This quite tricky, and you would be probably better off doing manual concatenation in a select query.
But since you asked for it...
In normal usage you would have used a computed column for this, but they do not support using autoincremented columns in their declaration. So you would need to use triggers:
on insert, query information_schema.tables to retrieve the autoincremented id that is about to be assigned and use it to generate the custom id
on update, reset the custom id
Consider the following table structure:
create table workers (
id int auto_increment primary key,
name varchar(50) not null,
dept varchar(1) not null,
custom_id varchar(12)
);
Here is the trigger for insert:
delimiter //
create trigger trg_workers_insert before insert ON workers
for each row
begin
if new.custom_id is null then
select auto_increment into #nextid
from information_schema.tables
where table_name = 'workers' and table_schema = database();
set new.custom_id = CONCAT(new.dept, lpad(#nextid, 11, 0));
end if;
end
//
delimiter ;
And the trigger for update:
delimiter //
create trigger trg_workers_update before update ON workers
for each row
begin
if new.dept is not null then
set new.custom_id = CONCAT(new.dept, lpad(old.id, 11, 0));
end if;
end
//
delimiter ;
Let's run a couple of inserts for testing:
insert into workers (dept, name) values ('A', 'John');
insert into workers (dept, name) values ('B', 'Jim');
select * from workers;
| id | name | dept | custom_id |
| --- | ---- | ---- | ------------ |
| 1 | John | A | A00000000001 |
| 2 | Jim | B | B00000000002 |
And let's test the update trigger
update workers set dept = 'C' where name = 'Jim';
select * from workers;
| id | name | dept | custom_id |
| --- | ---- | ---- | ------------ |
| 1 | John | A | A00000000001 |
| 2 | Jim | C | C00000000002 |
Demo on DB Fiddle
Sorry, my answer does not fit in a comment.
I agree with #GMB.
This is a tricky situation and in some cases (selects mainly) will lead in a performance risk due you'll have to split PK in where statements, which is not recommended.
Having a column for department and another for auto_increment is more logical. And the only gap you have is to know the number of employees per department you'll have to make a count grouping by dept. Instead of a max() splitting your concatenated PK, which is is at high performance cost.
Let atomic and logic data remain in separate columns. I would suggest to create a third column with the concatenated value.
If, for some company reason, you need B1 and A1 values for employees of different departments, I'd suggest to have 3 columns
Col1 - letter(not null)
Col2 - ID(Not auto-increment, but calculated as #GMB's solution) (Not NULL)
Col3 - Concatenation of Col1 and Col2 (not null)
PK( Col1, col2)

How to update based on json keys?

I have a table of an app setting that looks like this:
Code | Value |
---------------------
MAC_ADDR | 'SAMPLE'|
PC_OPT | 0 |
SHOW_ADDR | 1 |
Then I'm receiving a json in my trigger function like this:
{MAC_ADDR: 'NEWADDR', PC_OPT: 1, SHOW_ADDR: 0}
How do I perform an update based on all the keys from my json?
you can just use json_populate_record, eg:
t=# create table tj("MAC_ADDR" text, "PC_OPT" int, "SHOW_ADDR" int);
CREATE TABLE
t=# insert into tj select 'SAMPLE',0,1;
INSERT 0 1
t=# select * from tj;
MAC_ADDR | PC_OPT | SHOW_ADDR
----------+--------+-----------
SAMPLE | 0 | 1
(1 row)
t=# update tj set "MAC_ADDR"=j."MAC_ADDR", "PC_OPT"=j."PC_OPT", "SHOW_ADDR"=j."SHOW_ADDR"
from json_populate_record(null::tj,'{"MAC_ADDR": "NEWADDR", "PC_OPT": 1, "SHOW_ADDR": 0}') j
where true;
UPDATE 1
t=# select * from tj;
MAC_ADDR | PC_OPT | SHOW_ADDR
----------+--------+-----------
NEWADDR | 1 | 0
(1 row)
keep in mind - you did not specify PK or other column to update rows so all rows will be updated in example above. Which suits your data sample, but would not in case of more data
Update
I misunderstood the question, in (code, value) table it's even easier, eg:
update some_tbl
set "Value" = '{"MAC_ADDR": "NEWADDR", "PC_OPT": 1, "SHOW_ADDR": 0}'::json->'MAC_ADDR'
where "Code"='MAC_ADDR'
o again, using the code above you can map update with json keys...

Cut of a specific part of a string with variable lenght and update it into another column

I have a table A that contains 2 columns - 1 of em with entries. In column 1 campaign-name . In column 2 i Want to insert a specific part of the campaign-name. Sound really simple, but the lenght of the campaign-name is variabe (but the structure is always the same)...
Here´s an example:
For example if the table A contained (till now):
|col1 ||col2 |
+-------------------------------+---------------+
|17_0102_LC_UpBirthday_LCAll_DE || |
|17_0102_News_Luxus_1_DE || |
|17_0105_News_SDT_1_DE || |
|17_0108_LC_UpBirthday_LCAll_NL || |
I want a query that will "produce":
|col1 ||col2 |
+-------------------------------+---------------+
|17_0102_LC_UpBirthday_LCAll_DE ||LC_UpBirthday |
|17_0102_News_Luxus_1_DE ||News_Luxus |
|17_0105_News_SDT_1_DE ||News_SDT |
|17_0108_LC_UpBirthday_LCAll_NL ||LC_UpBirthday |
-> I allways want the part between the second and forth '_' of the string
This what I got so far (must be sth. that works with substring & instr I recon):
UPDATE A SET col2 = SUBSTRING(col1, INSTR(col1, '_');
-> but of course, this is not working, it´s just a solution approach ...

update if two fields exists, insert if not (MySQL)

This isn't an (exact) duplicate of this questions so I'Ve started a new one.
I have this table (ID is primary and auto increment)
ID | mykey | myfoo | mybar
============================
1 | 1.1 | abc | 123
2 | 1.1.1 | def | 456
3 | 1.2 | abc | 789
4 | 1.1 | ghi | 999
I would like to UPDATE row 1 with mybar = "333" only if mykey = '1.1' AND myfoo = 'abc'
If either mykey != '1.1' OR myfoo != 'abc' I would like to INSERT an new row.
Is this possible with one statement?
A unique index in MySQL does not have to be on a single column. You can add a UNIQUE index on multiple columns simply by specifying more columns in your ALTER TABLE..ADD UNIQUE statement:
ALTER TABLE myTable ADD UNIQUE (
mykey,
myfoo
);
Now you can use a regular INSERT INTO...ON DUPLICATE KEY statement.
SQLFiddle DEMO (note that the multiple repeated values are not added - all others are)
Note:
If either is NULL, it will not be counted as unique. mykey being 'bar' and myfoo being NULL could be added to infinity even though they have the "same" values (NULL isn't really a value).