Your best bet would still be MD5, or hash() but with a few changes to the strategy.
Consider converting NULLs to a distinct, consistent string in the checksum calculation (e.g., 'NULL'). In a way, to helps ensures NULLs are treated differently from empty strings ('') or zeros (0). Conversely, treat empty strings ('') also as distinct values by preserving them in the string representation. Ensure empty strings are not conflated with NULLs by explicitly including them in the concatenation.
Consider converting all column values to a string representation before hashing. For numeric types, you could trim trailing zeroes (2.0 becomes 2). Similarly, consider using a simple timestamp format for representations of date as well as time. For booleans, map to consistent strings (e.g., TRUE → '1', FALSE → '0').
Lastly, if you are going for concatenation, make sure that the delimiter is chosen so that it doesn't appear in the data often, like ~.
If you can manage nulls and empty strings (and zeroes), then perhaps MD5 could be the most feasible. But it requires some human intervention to set the data right.