While working with a customer recently, I saw some code from them that used the OUTPUT and INTO clauses of an UPDATE statement to capture the changes made into another table. In this case, as users updated code strings in a table used in dynamic SQL, the developers wanted to capture the history of those changes in another table, giving them a rollback strategy if there were problems. This is an interesting, and focused way of auditing data changes, albeit with the work to write this code and control updates through stored procedures.
This is one way of tracking the history of data values in many database platforms. Temporal tables are another, and we have CDC/Change Capture available in SQL Server. In the past, many people have used triggers. All of these work, with various pros and cons. In many cases, I have seen triggers used, often because many developers know how to write them and they are easy to create. Easy to get wrong as well.
However, triggers take some work, while platforms have often built capabilities that make it easy to capture data changes and track them. Many developers often aren't aware of these features, or haven't spent sufficient time with them to know how to work with them or if these features even work well. This is one reason many of us write about new features, to learn about them, experiment, and help others to understand how to use them. Of course, not all features turn out to be as great as marketed.
Today I wonder how you capture changes and audit them. Do you use triggers? Something built in? For limited auditing, and with control of the code, would you use the OUTPUT clause with your insert/update/delete code? Actually, I wonder how many of you would even consider this for limited auditing, especially with the large number of tools and frameworks that might generate their own UPDATE statement rather than call a stored procedure where you control the code. Or do you think this isn't a good way to capture this data.