Ah, the perils of copy and paste coding.
Putting
use warnings at the top of your file might help. (Not sure how it interacts with CGI::Carp, though. Debuggering CGIs always sucks.)
Let's go over what your code is actually doing, and it should be clear where the problem is. (Clear as mud still counts.)
Code:
print header;
print start_html;
"header" and "start_html" are subs defined in the CGI module. The header sub returns the headers that a CGI passes to a web browser. The start_html sub just returns "<html>", indicating an html document.
Code:
$sth = $dbh->prepare($sql);
$res = $sth->execute();
Okay... you're telling the database handle $dbh to prepare a SQL statement stored in the variable $sql, and the result is a statement handle which you assign to $sth. Is something missing here?
You then executed the prepared statement and the result has been stored in $res.
Code:
$dbh = ("INSERT INTO user_accounts (username, email, password)
VALUES ($NewUserName, $NewEmail, $CryptPassword)");
Here you are combining some values to create a string. The parens aren't necessary, incidentally. The resulting string is going to be something like:
Code:
INSERT INTO user_accounts (username, email, password) VALUES (bob, bob@foo.com, ow34if)
SQL injection is bad, mmkay. Use placeholders, mmkay.
Here are the docs on placeholders. It can be tricky, but if you don't use placeholders any idiot can run arbitrary code on your system. If you have a variable number of values to splice in, use the $dbh->quote() function.
You've now assigned that string to your variable $dbh.
Code:
$sth->finish();
$dbh->disconnect();
Now you've called finish on your statement handle. What did that accomplish? Read the docs to find out. You then tried to call disconnect on your malformed SQL string, which is where you ran into the error.
Handy links:
the docs for DBI and
for the MySQL driver.