SQL function from Latin to Cyrillic - tsql

I am looking for ms sql function to make translit from Latin to Cyrillic. Does anybody have completed solution? (for example, 'spasibo' -> 'спасибо')

CREATE FUNCTION dbo.ToCyrillic
(
#str Nvarchar(MAX)
)
RETURNS Nvarchar(MAX)
AS
BEGIN
-- Declare the return variable here
DECLARE #inputLength int
DECLARE #i int
DECLARE #latinSymbol nVarchar(2)
DECLARE #cyrillicSymbol nVarchar(2)
DECLARE #outputValue nVarchar(MAX)
SET #outputValue=N''
SET #inputLength=LEN(#str)
SET #i=1
DECLARE #TransTable table (upperCyr nvarchar(2) COLLATE Cyrillic_General_CI_AS,
lowerCyr nvarchar(2) COLLATE Cyrillic_General_CI_AS,
lowerLat nvarchar(2), cid int PRIMARY KEY IDENTITY(1,1))
insert into #TransTable values (N'А', N'а', N'a')
insert into #TransTable values (N'Б', N'б', N'b')
insert into #TransTable values (N'В', N'в', N'v')
insert into #TransTable values (N'Г', N'г', N'g')
insert into #TransTable values (N'Д', N'д', N'd')
insert into #TransTable values (N'Ђ', N'ђ', N'đ')
insert into #TransTable values (N'Е', N'е', N'e')
insert into #TransTable values (N'Ж', N'ж', N'ž')
insert into #TransTable values (N'З', N'з', N'z')
insert into #TransTable values (N'И', N'и', N'i')
insert into #TransTable values (N'Ј', N'ј', N'j')
insert into #TransTable values (N'К', N'к', N'k')
insert into #TransTable values (N'Л', N'л', N'l')
insert into #TransTable values (N'Љ', N'љ', N'lj')
insert into #TransTable values (N'М', N'м', N'm')
insert into #TransTable values (N'Н', N'н', N'n')
insert into #TransTable values (N'Њ', N'њ', N'nj')
insert into #TransTable values (N'О', N'о', N'o')
insert into #TransTable values (N'П', N'п', N'p')
insert into #TransTable values (N'Р', N'р', N'r')
insert into #TransTable values (N'С', N'с', N's')
insert into #TransTable values (N'Т', N'т', N't')
insert into #TransTable values (N'Ћ', N'ћ', N'ć')
insert into #TransTable values (N'У', N'у', N'u')
insert into #TransTable values (N'Ф', N'ф', N'f')
insert into #TransTable values (N'Х', N'х', N'h')
insert into #TransTable values (N'Ц', N'ц', N'c')
insert into #TransTable values (N'Ч', N'ч', N'č')
insert into #TransTable values (N'Џ', N'џ', N'dž')
insert into #TransTable values (N'Ш', N'ш', N'š')
WHILE (#i<=#inputLength)
BEGIN
SET #latinSymbol=SUBSTRING(#str,#i,1)
SET #cyrillicSymbol=#latinSymbol -- If not found below, then use that char (e.g. numbers etc)
IF ((#latinSymbol COLLATE Croatian_CS_AS)=UPPER(#latinSymbol))
BEGIN
SELECT TOP 1 #cyrillicSymbol=upperCyr FROM #TransTable WHERE lowerlat=lower(#latinSymbol) ORDER BY CID
END
ELSE
BEGIN
SELECT TOP 1 #cyrillicSymbol=lowerCyr FROM #TransTable WHERE lowerlat=lower(#latinSymbol) ORDER BY CID
END
SET #i=#i+1
set #outputValue=#outputValue+#cyrillicSymbol
END
RETURN #outputValue
END

It's good function dbo.ToCyrillic, but not good enough. It's tree exceptions Љ=lj, Њ=nj, Џ=dž.
This is alter function dbo.ToCyrillic with exceptions:
-- select dbo.ToCyrillic('Ljubav nJače džače')
ALTER FUNCTION [dbo].[ToCyrillic](#str Nvarchar(MAX))
RETURNS Nvarchar(MAX)
AS
BEGIN
-- Declare the return variable here
DECLARE #inputLength int
DECLARE #i int
DECLARE #latinSymbol nVarchar(2)
DECLARE #latinSymbol2 nVarchar(2)
set #latinSymbol2=null
DECLARE #cyrillicSymbol nVarchar(2)
DECLARE #outputValue nVarchar(MAX)
SET #outputValue=N''
SET #inputLength=LEN(#str)
SET #i=1
DECLARE #TransTable table (upperCyr nvarchar(2) COLLATE Cyrillic_General_CI_AS,
lowerCyr nvarchar(2) COLLATE Cyrillic_General_CI_AS,
lowerLat nvarchar(2), cid int PRIMARY KEY IDENTITY(1,1))
insert into #TransTable values (N'А', N'а', N'a')
insert into #TransTable values (N'Б', N'б', N'b')
insert into #TransTable values (N'В', N'в', N'v')
insert into #TransTable values (N'Г', N'г', N'g')
insert into #TransTable values (N'Д', N'д', N'd')
insert into #TransTable values (N'Ђ', N'ђ', N'đ')
insert into #TransTable values (N'Е', N'е', N'e')
insert into #TransTable values (N'Ж', N'ж', N'ž')
insert into #TransTable values (N'З', N'з', N'z')
insert into #TransTable values (N'И', N'и', N'i')
insert into #TransTable values (N'Ј', N'ј', N'j')
insert into #TransTable values (N'К', N'к', N'k')
insert into #TransTable values (N'Л', N'л', N'l')
insert into #TransTable values (N'Љ', N'љ', N'lj')
insert into #TransTable values (N'М', N'м', N'm')
insert into #TransTable values (N'Н', N'н', N'n')
insert into #TransTable values (N'Њ', N'њ', N'nj')
insert into #TransTable values (N'О', N'о', N'o')
insert into #TransTable values (N'П', N'п', N'p')
insert into #TransTable values (N'Р', N'р', N'r')
insert into #TransTable values (N'С', N'с', N's')
insert into #TransTable values (N'Т', N'т', N't')
insert into #TransTable values (N'Ћ', N'ћ', N'ć')
insert into #TransTable values (N'У', N'у', N'u')
insert into #TransTable values (N'Ф', N'ф', N'f')
insert into #TransTable values (N'Х', N'х', N'h')
insert into #TransTable values (N'Ц', N'ц', N'c')
insert into #TransTable values (N'Ч', N'ч', N'č')
insert into #TransTable values (N'Џ', N'џ', N'dž')
insert into #TransTable values (N'Ш', N'ш', N'šˇ')
WHILE (#i<=#inputLength)
BEGIN
SET #latinSymbol=SUBSTRING(#str,#i,1)
SET #cyrillicSymbol=#latinSymbol -- If not found below, then use that char (e.g. numbers etc)
-- exceptions Љ,Њ,Џ
if (#i+1<=#inputLength) set #latinSymbol2=SUBSTRING(#str,#i+1,1)
if lower(#latinSymbol+#latinSymbol2) in ('lj','nj','dž')
begin
if ((#latinSymbol COLLATE Croatian_CS_AS)=UPPER(#latinSymbol))
BEGIN
SELECT TOP 1 #cyrillicSymbol=upperCyr FROM #TransTable WHERE lowerlat=lower(#latinSymbol+#latinSymbol2) ORDER BY CID
END
ELSE
BEGIN
SELECT TOP 1 #cyrillicSymbol=lowerCyr FROM #TransTable WHERE lowerlat=lower(#latinSymbol+#latinSymbol2) ORDER BY CID
END
SET #i=#i+2
end
else--end exceptions
begin
IF ((#latinSymbol COLLATE Croatian_CS_AS)=UPPER(#latinSymbol))
BEGIN
SELECT TOP 1 #cyrillicSymbol=upperCyr FROM #TransTable WHERE lowerlat=lower(#latinSymbol) ORDER BY CID
END
ELSE
BEGIN
SELECT TOP 1 #cyrillicSymbol=lowerCyr FROM #TransTable WHERE lowerlat=lower(#latinSymbol) ORDER BY CID
END
SET #i=#i+1
end
set #outputValue=#outputValue+#cyrillicSymbol
END
RETURN #outputValue
END

Related

How to create trigger that calculate delta between two tables?

I have three tables. I need create trigger that calculate price difference between two tables and insert it to result table.
Algorithm is next:
If we inserting value in table2 we should check if table1 have same id, get start_price from it, calculate difference, and insert result in result table.
For example if we are insering (assume table1 is already filled) :
INSERT INTO table2 VALUES (1, 135);
we should get in result table:
1 3.58%
caculation logic: 100-((135/140) * 100) = 3.58%
I can't figure out how to do this math operation inside trigger:
CREATE TABLE table1
(
id integer NOT NULL,
start_price integer NOT NULL,
CONSTRAINT table1_pkey PRIMARY KEY (id)
);
CREATE TABLE table2
(
id integer NOT NULL,
end_price integer NOT NULL
);
CREATE TABLE result
(
id integer NOT NULL,
result_price decimal NOT NULL
);
INSERT INTO table1 VALUES (1, 140);
INSERT INTO table1 VALUES (2, 230);
INSERT INTO table1 VALUES (3, 70);
trigger:
CREATE OR REPLACE FUNCTION delta_percent_calc() RETURNS TRIGGER AS
$BODY$
BEGIN
INSERT INTO
result(id,name)
-- some logic here. seems that INSERT or UPDATE should be here because table1 and table2 price can be changed with update
RETURN new;
END;
$BODY$
language plpgsql;
UPD:. it's seems that I get it work with follow solution:
CREATE OR REPLACE FUNCTION delta_percent_calc() RETURNS TRIGGER AS
$BODY$
DECLARE
s_price integer;
BEGIN
select start_price into s_price from table1 where id = new.id;
INSERT INTO
result (id,result_price)
VALUES(new.id, round(100 - ( (new.end_price::numeric/s_price::numeric) * 100), 4 ) );
ON CONFLICT (id) DO UPDATE
SET result_price = round(100 - ( (new.end_price::numeric/s_price::numeric) * 100), 4 );
RETURN new;
END;
$BODY$
language plpgsql;
CREATE OR REPLACE TRIGGER trig_percent_calc
AFTER INSERT ON table2
FOR EACH ROW
EXECUTE PROCEDURE delta_percent_calc();

Postgres exclude using gist across different tables

I have 2 tables like this
drop table if exists public.table_1;
drop table if exists public.table_2;
CREATE TABLE public.table_1 (
id serial NOT NULL,
user_id bigint not null,
status varchar(255) not null,
date_start date NOT NULL,
date_end date NULL
);
CREATE TABLE public.table_2 (
id serial NOT NULL,
user_id bigint not null,
status varchar(255) not null,
date_start date NOT NULL,
date_end date NULL
);
alter table public.table_1
add constraint my_constraint_1
EXCLUDE USING gist (user_id with =, daterange(date_start, date_end, '[]') WITH &&)
where (status != 'deleted');
alter table public.table_2
add constraint my_constraint_2
EXCLUDE USING gist (user_id with =, daterange(date_start, date_end, '[]') WITH &&)
where (status != 'deleted');
Every table contains rows which are related to a user, and all the rows of the same user cannot overlap in range. In addition, some rows may be logically deleted, so I added a where condition.
So far it's working w/o problems, but the 2 constraints work separately for each table.
I need to create a constraint which cover the 2 set of tables, so that a single daterange (of the same user and not deleted), may appaer only once across the 2 different tables.
Does the EXCLUDE notation be extended to work with different tables or do I need to check it with a trigger? If the trigger is the answer, which is the simplier way to do this? Create a temporary table with the union of the 2, add the constraint on it and check if fails?
Starting from #Laurenz Albe suggestion, this is what I made
-- #################### SETUP SAMPLE TABLES ####################
drop table if exists public.table_1;
drop table if exists public.table_2;
CREATE TABLE public.table_1 (
id serial NOT NULL,
user_id bigint not null,
status varchar(255) not null,
date_start date NOT NULL,
date_end date NULL
);
CREATE TABLE public.table_2 (
id serial NOT NULL,
user_id bigint not null,
status varchar(255) not null,
date_start date NOT NULL,
date_end date NULL
);
alter table public.table_1
add constraint my_constraint_1
EXCLUDE USING gist (user_id with =, daterange(date_start, date_end, '[]') WITH &&)
where (status != 'deleted');
alter table public.table_2
add constraint my_constraint_2
EXCLUDE USING gist (user_id with =, daterange(date_start, date_end, '[]') WITH &&)
where (status != 'deleted');
-- #################### SETUP TRIGGER ####################
create or REPLACE FUNCTION check_date_overlap_trigger_hook()
RETURNS trigger as
$body$
DECLARE
l_table text;
l_sql text;
l_row record;
begin
l_table := TG_ARGV[0];
l_sql := format('
select *
from public.%s as t
where
t.user_id = %s -- Include only records of the same user
and t.status != ''deleted'' -- Include only records that are active
', l_table, new.user_id);
for l_row in execute l_sql
loop
IF daterange(l_row.date_start, COALESCE(l_row.date_end, 'infinity'::date)) && daterange(new.date_start, COALESCE(new.date_end, 'infinity'::date))
THEN
RAISE EXCEPTION 'Date interval is overlapping with another one in table %', l_table
USING HINT = 'You can''t have the same interval across table1 AND table2';
END IF;
end loop;
RETURN NEW;
end
$body$
LANGUAGE plpgsql;
-- #################### INSTALL TRIGGER ####################
create trigger check_date_overlap
BEFORE insert or update
ON public.table_1
FOR EACH row
EXECUTE PROCEDURE check_date_overlap_trigger_hook('table_2');
create trigger check_date_overlap
BEFORE insert or update
ON public.table_2
FOR EACH row
EXECUTE PROCEDURE check_date_overlap_trigger_hook('table_1');
-- #################### INSERT DEMO ROWS ####################
insert into public.table_1 (user_id, status, date_start, date_end) values (1, 'active', '2020-12-10', '2020-12-20');
insert into public.table_1 (user_id, status, date_start, date_end) values (1, 'deleted', '2020-12-15', '2020-12-25');
insert into public.table_1 (user_id, status, date_start, date_end) values (2, 'active', '2020-12-10', '2020-12-20');
insert into public.table_1 (user_id, status, date_start, date_end) values (2, 'deleted', '2020-12-15', '2020-12-25');
-- This will fail for overlap on the same table
-- insert into public.table_1 (user_id, status, date_start, date_end) values (1, 'active', '2020-12-15', '2020-12-25');
-- This will fail as the user 1 already has an overlapping period on table 1
-- insert into public.table_2 (user_id, status, date_start, date_end) values (1, 'active', '2020-12-15', '2020-12-25');
-- This will fail as the user 1 already has an overlapping period on table 1
insert into public.table_2 (user_id, status, date_start, date_end) values (1, 'deleted', '2020-12-15', '2020-12-25');
update public.table_2 set status = 'active' where id = 1;
select 'table_1' as src_table, * from public.table_1
union
select 'table_2', * from public.table_2
You can probably use a trigger, but triggers are always vulnerable to race conditions (unless you are using SERIALIZABLE isolation).
If your tables really have the same columns, why don't you use a single table (and perhaps add a type column to disambiguate)?

Replace ID column in LTREE with different column Postgres

I have a hierarchical structure in postgres which uses LTREE to calculate path based on a trigger. I am following the examples from here: https://coderwall.com/p/whf3-a/hierarchical-data-in-postgres
Table, trigger and data being inserted look like this:
CREATE TABLE section (
id INTEGER PRIMARY KEY,
asset_name TEXT,
parent_id INTEGER REFERENCES section,
parent_path LTREE
);
CREATE INDEX section_parent_path_idx ON section USING GIST (parent_path);
CREATE INDEX section_parent_id_idx ON section (parent_id);
CREATE OR REPLACE FUNCTION update_section_parent_path() RETURNS TRIGGER AS $$
DECLARE
path ltree;
BEGIN
IF NEW.parent_id IS NULL THEN
NEW.parent_path = '6'::ltree;
ELSEIF TG_OP = 'INSERT' OR OLD.parent_id IS NULL OR OLD.parent_id != NEW.parent_id THEN
SELECT parent_path || id::text FROM section WHERE id = NEW.parent_id INTO path;
IF path IS NULL THEN
RAISE EXCEPTION 'Invalid parent_id %', NEW.parent_id;
END IF;
NEW.parent_path = path;
END IF;
ltree_array = (STRING_TO_ARRAY(path::TEXT,'.'))[2:2147483647];
IF ltree_array IS NOT NULL THEN
FOREACH entry IN ARRAY(ltree_array)
LOOP
v_asset_name = (SELECT asset_name
FROM section AS s
WHERE s.id = entry);
s3path = s3path || v_asset_name || '/';
END LOOP;
END IF;
s3path = NEW.asset_store_id || '/' || s3path || NEW.asset_name;
NEW.s3_path = s3path;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER parent_path_tgr
BEFORE INSERT OR UPDATE ON section
FOR EACH ROW EXECUTE PROCEDURE update_section_parent_path();
INSERT INTO section (id, asset_name, parent_id ) VALUES (1, 'Main Folder', NULL);
INSERT INTO section (id, asset_name, parent_id ) VALUES (2, 'Rejected', 1);
INSERT INTO section (id, asset_name, parent_id ) VALUES (3, 'Records', NULL);
INSERT INTO section (id, asset_name, parent_id ) VALUES (4, 'Expired', 3);
INSERT INTO section (id, asset_name, parent_id ) VALUES (5, 'Selected', 3);
INSERT INTO section (id, asset_name, parent_id ) VALUES (6, 'Useless', 5);
The table output looks like this:
id|asset_name |parent_id|parent_path|
--|-----------|---------|-----------|
1|Main Folder| |6 |
2|Rejected | 1|6.1 |
3|Records | |6 |
4|Expired | 3|6.3 |
5|Selected | 3|6.3 |
6|Useless | 5|6.3.5 |
parent_path is all numerical because it looks like it is concatinating id, but I want to concatinate asset_name column.
I have tried replacing id with asset_name but that throws an syntax error. I can't seem to figure out how to replace id within the trigger.

Postgres INSERT ON CONFLICT behavior with INSTEAD OF trigger

Suppose I have the following tables and view:
CREATE TABLE table_a(
field_x INTEGER PRIMARY KEY,
id SERIAL UNIQUE
);
CREATE TABLE table_b(
a_id INTEGER PRIMARY KEY REFERENCES table_a(id),
field_y INTEGER NOT NULL
);
CREATE VIEW v AS SELECT * FROM table_a JOIN table_b ON table_a.id=table_b.a_id;
I want to be able to insert into the view, so I created the following function and trigger:
CREATE FUNCTION insert_into_view()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $function$
DECLARE new_id INTEGER;
BEGIN
IF TG_OP = 'INSERT' THEN
INSERT INTO table_a (field_x) VALUES (NEW.field_x) ON CONFLICT DO NOTHING RETURNING id INTO new_id;
IF new_id IS NULL THEN
SELECT id FROM table_a WHERE field_x=NEW.field_x INTO new_id;
END IF;
INSERT INTO table_b (a_id, field_y) VALUES (new_id, NEW.field_y);
END IF;
RETURN NEW;
END;
$function$;
CREATE TRIGGER view_insert_trigger
INSTEAD OF INSERT ON
v FOR EACH ROW EXECUTE PROCEDURE insert_into_view();
Now I want to insert values into the view only if there does not exist a row for field_x yet in the view, e.g.:
INSERT INTO v (field_x, field_y) VALUES (5,6);
INSERT INTO v (field_x, field_y) VALUES (5,8) ON CONFLICT DO NOTHING;
Where I want the second insert to silently do nothing. However, I get this:
ERROR: duplicate key value violates unique constraint "table_b_pkey"
DETAIL: Key (a_id)=(2) already exists.
CONTEXT: SQL statement "INSERT INTO table_b (a_id, field_y) VALUES (new_id, NEW.field_y)"
I know why I'm getting this error: the function insert_into_view does not specify ON CONFLICT behavior when inserting into table_b and by default the query fails. Thus my question: can I make the ON CONFLICT behavior to ripple from the view insert into the table insert? (I may want to specify different conflict behavior at a later time, so I don't want to hard-code this in the trigger function if I can avoid it.)
Thanks!
I'm still not sure If I understand you right. But I try:
if you change
INSERT INTO table_b (a_id, field_y) VALUES (new_id, NEW.field_y)
to
INSERT INTO table_b (a_id, field_y) VALUES (new_id, NEW.field_y) ON CONFLICT DO NOTHING
in function it will start working silently.
Regarding
INSERT INTO v (field_x, field_y) VALUES (5,8) ON CONFLICT DO NOTHING;
I think you can use ON CONFLICT only on tables with unique constraint, so and foreign table, and instead rule will ignore ON CONFLICT DO NOTHING and fail when you specify target_name of constraint_name

PostgreSQL: Iterate through a tables rows with for loop, retrieve column value based on current row

I have the following 2 tables
CREATE TABLE salesperson_t (
salespersonid numeric(4,0) NOT NULL,
salespersonname character varying(25),
salespersontelephone character varying(50),
salespersonfax character varying(50),
salespersonaddress character varying(30),
salespersoncity character varying(20),
salespersonstate character(2),
salespersonzip character varying(20),
salesterritoryid numeric(4,0),
CONSTRAINT salesperson_pk PRIMARY KEY (salespersonid)
);
INSERT INTO salesperson_t VALUES (1, 'Doug Henny', '8134445555', NULL, NULL, NULL, NULL, NULL, 2);
INSERT INTO salesperson_t VALUES (2, 'Robert Lewis', '8139264006', NULL, '124 Deerfield', 'Lutz', 'FL', '33549', 13);
INSERT INTO salesperson_t VALUES (3, 'William Strong', '3153821212', NULL, '787 Syracuse Lane', 'Syracuse', 'NY', '33240', 3);
INSERT INTO salesperson_t VALUES (4, 'Julie Dawson', '4355346677', NULL, NULL, NULL, NULL, NULL, 4);
INSERT INTO salesperson_t VALUES (5, 'Jacob Winslow', '2238973498', NULL, NULL, NULL, NULL, NULL, 5);
INSERT INTO salesperson_t VALUES (6, 'Pepe Lepue', NULL, NULL, NULL, 'Platsburg', 'NY', NULL, 13);
INSERT INTO salesperson_t VALUES (8, 'Fred Flinstone', NULL, NULL, '1 Rock Lane', 'Bedrock', 'Ca', '99999', 2);
INSERT INTO salesperson_t VALUES (9, 'Mary James', '3035555454', NULL, '9 Red Line', 'Denver', 'CO', '55555', 4);
INSERT INTO salesperson_t VALUES (10, 'Mary Smithson', '4075555555', NULL, '4585 Maple Dr', 'Orlando', 'FL', '32826', 15);
CREATE TABLE territory2_t (
territoryid numeric(4,0),
territoryname character varying(50),
total_sales_person integer,
CONSTRAINT territory2_t_pk PRIMARY KEY (territoryid)
);
INSERT INTO territory2_t VALUES (1, 'SouthEast', NULL);
INSERT INTO territory2_t VALUES (2, 'SouthWest', NULL);
INSERT INTO territory2_t VALUES (3, 'NorthEast', NULL);
INSERT INTO territory2_t VALUES (4, 'NorthWest', NULL);
INSERT INTO territory2_t VALUES (5, 'Central', NULL);
INSERT INTO territory2_t VALUES (6, 'Alaska', NULL);
INSERT INTO territory2_t VALUES (12, 'Hawaii', NULL);
INSERT INTO territory2_t VALUES (13, 'Colorado', NULL);
INSERT INTO territory2_t VALUES (15, 'Arizona', NULL);
I have the following pseudo code:
DO $$
DECLARE
-- currentRow [relevant datatype];
BEGIN
FOR counter IN 1..(SELECT count(*)FROM territory2_t) LOOP -- There are 13 total rows
-- **assign currentRow to counter**
RAISE NOTICE 'Counter: %', counter; -- debugging purposes
UPDATE terriory2_t
SET total_sales_person = ((SELECT count(*)
FROM salesperson_t
WHERE salesterritoryid = currentRow.territoryid)*1) -- *1 is for debuggin puporses
WHERE territoryid = currentRow.territoryid;
-- **increase currentRow by 1**
END LOOP;
END; $$
It's purpose is count how many rows in the table (salesperson) have the 'territoryid' of the the currentRows->'territory2.territoryid', and then assign that quantity to currentRows->territory2.total_sales_person.
You don't need a loop or even a function for this.
What you want to do can be done in a single update statement because the total count per territory can be calculated with a single aggregation:
SELECT salesterritoryid, count(*) as total_count
FROM salesperson_t
group by salesterritoryid
This can then be used as the source to update the territory table:
UPDATE territory2_t
SET total_sales_person = t.total_count
FROM (
SELECT salesterritoryid, count(*) as total_count
FROM salesperson_t
group by salesterritoryid
) t
WHERE territoryid = t.salesterritoryid;
An alternative that might be easier to understand but will be slower for larger tables is an update with a co-related sub-query
UPDATE territory2_t tg
SET total_sales_person = (select count(*)
from salesperson_t sp
where sp.salesterritoryid = tg.territoryid);
There is a slight difference between the first and second update: the second one will update the total_sales_person to 0 (zero) for those territories where there is no salesperson at all. The first one will only update the count for territories that are actually present in the salesperson table.
Unrelated, but: having a "type identifying" prefix or suffix for an identifier is usually useless and doesn't really help at all. See a related discussion on dba.stackexchange