This really has nothing to do with Perl or DBI. You can do it with a single SQL, barring minor SQL dialect variations (you don't mention what database you're using).
SELECT *
INTO sp_err
FROM sp
WHERE NOT EXISTS (
SELECT 1
FROM supplier
WHERE sp.num = supplier.num
)
If you have to execute that from Perl, just put the whole thing in a
$dbh->do(...).
Update
The SELECT * INTO form is non-standard SQL that's supported only a few places (Sybase comes to mind). The equivalent in standard SQL, presuming sp and sp_err have the same columns, would be:
INSERT INTO sp_err
SELECT * FROM sp
WHERE NOT EXISTS (
SELECT 1
FROM supplier
WHERE sp.num = supplier.num
)
As to "moving" rows: your original post didn't do that: it only inserted rows into
sp_err. As to why it didn't work, see my reply elsewhere in this thread.