A statement is syntactically correct if it meets the rules of SQL: the keywords are spelt correctly, in the right place, etc.
For example, the following has invalid syntax:
slct * frm a_table;
Unknown Command
The semantic happens for statements with valid syntax. This verifies that the objects you've referenced really exist!
For example, the following is syntactically valid SQL. But it raises a semantic error because there's no object called a_table in the database!
select * from a_table;
ORA-00942: table or view does not exist
For the most part, you don't need to worry about this difference in PL/SQL. You can only compile programs with static SQL if they're syntactically and semantically valid. So you don't have to worry about exception handling, because the PL/SQL itself won't run!
The key exception is if you're writing dynamic SQL.
create table t (
c1 int
);
insert into t values ( 1 );
commit;
create or replace function f
return int authid current_user as
retval int;
begin
execute immediate
'select count(*) from not_a_real_table'
into retval;
return retval;
end f;
/
select f from dual;
ORA-00942: table or view does not exist
create or replace function f
return int authid current_user as
retval int;
begin
execute immediate
'slct count(*) fr not_a_real_table'
into retval;
return retval;
end f;
/
select f from dual;
ORA-00900: invalid SQL statement
But even here, I'm not sure why you care about the difference between syntax vs semantics. In either case your program fails. And the ORA error will give details about what the issue is.