Can it be shorter?: DNA Sequence Analyzer from CS50 written in Python
I would group the code in functions and call them from a central main. With how you have it now, simply loading the file into an interactive console will cause all the code to run, which, if the code is long running or causes side-effects, may be less than ideal. Say I wrote a port-scanner, and it takes 2-3 minutes to run. I may not want it to start simply because I loaded the file into a REPL in Pycharm. Not only would that waste a few minutes each time, port-scanning can get you in trouble if done on a network that you don't have permission to scan.
Code wrapped in functions is simply easier to control the execution of, because it will only run when the function is called.
Grouping code into functions also allows you to easily test each chunk in isolation from the rest of the code. It's difficult to test code when you're dependent on the first half of the code to supply test data to the latter-half. It's much easier however to simply load the script into a REPL, and throw test data at the function (or use proper unit-tests). Then you can test one piece of code in isolation without touching the rest of the code.

I personally believe that STRs and STR should be lower-case. According to PEP8, Python's style and convention guide, regular variables should be lower case, with words separated by underscores. Variables that are considered to be constants however should be upper-case, separated by underscores.
Local variables that remain unchanged have never clicked as &quot;constants&quot; in my head, so it depends on what you decide.
Regardless though, STRs should either be all upper-case, or all lower-case; in which case the STR counterpart will need to be renamed so it doesn't clash with the str built-in. A name like str_ could be used, or you could use a more descriptive name.

compare = {}

. . .

for key, value in row.items():
    compare[key] = int(value)

This can make use of a dictionary comprehension. Whenever you have the pattern of creating a set/list/dictionary before a loop, then populating the structure within the loop, you should consider a comprehension:
compare = {key: int(value) for key, value in row.items()}


Similarly, to ensure that a condition holds for an entire collection (or two in this case), you can combine all with a generator expression (the part passed to all):
if all(compare[STR] == str_counts[STR] for STR in STRs):
    matched = True
    print(match_name)

&quot;If all corresponding values in the two dictionaries match, set the matched flag&quot;. It reads quite nicely.
That gets rid of the need for match_count, and the second last loop.

You're looping more than you need to. You appear to only care about if at least one match is found; yet you keep looping even after one is.
I'd break once one is found. If you combine that with for's else clause, you can prevent unnecessary looping and still detect failure:
for row in db:
    . . .
    if all(compare[STR] == str_counts[STR] for STR in STRs):
        print(match_name)
        break

else:
    print(&quot;No Match&quot;)