Category: Blog

  • The Book of Redgate: Ingeniously Simple

    Redgate has been known for many useful tools that are easy to use. We’ve tried to do that in all our point tools. We talk about simplicity all the time and when we release something that isn’t simple, lots of people question why.

    Perhaps not enough or with enough pushback, but we do talk about simplicity.

    One of the pages in the book was devoted to merely expressing ingeniously simple. It’s written in a number of languages.

    2025-05_0105

    The goal of ingenious simplicity is to build things that people can use without resorting to complex manuals and example code. SQL Compare is a great example of this. Enter a few database connections and click Compare and you get an easy report. There’s a big Deploy button on top to help you sync your databases.

    I think we’ve done a good job of building some simple tools over the years. Perhaps now we’re in a more complex environment, but we are trying to keep things simple and provide clues to help users understand how the tools work.

    I have a copy of the Book of Redgate from 2010. This was a book we produced internally about the company after 10 years in existence. At that time, I’d been there for about 3 years, and it was interesting to learn a some things about the company. This series of posts looks back at the Book of Redgate 15 years later.

  • A Basic Update Trigger: #SQLNewBlogger

    I had someone ask me about using triggers to detect changes in their tables. As I explained a few things, I thought this would make a nice series, so I’ve written a few posts on triggers that can be useful. This one looks at detecting a change to a column in a trigger.

    Another post for me that is simple and hopefully serves as an example for people trying to get blogging as #SQLNewBloggers.

    The Setup

    I’ve got a Customer table that I want to use, which doesn’t have any triggers on it. Here is the schema.

    CREATE TABLE [dbo].[Customer](
         [CustomerID] [int] NOT NULL,
         [CustomerName] [varchar](200) NOT NULL,
         [AddressKey] [int] NULL,
         [CustomerStatus] [int] NULL,
         [CustomerContact] [varchar](100) NULL,
         [ContactEmail] [varchar](100) NULL,
      CONSTRAINT [CustomerPK] PRIMARY KEY CLUSTERED 
    (
         [CustomerID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    I also have a logging table where I can store messages from a trigger, which is better than direct output.

    Let’s create a trigger. I’ll use an UPDATE trigger here to check if a column is changed and then insert a logging message.

    Note: I’m not trying to be efficient here, just create an action based on what changed. THIS IS NOT PRODUCTION QUALITY CODE.

    Here is a basic trigger using the UPDATE() function to check if a column changed. I am inserting into the logger table when I detect a change, but in a real application, I’d likely have some business logic here instead of the insert.

    CREATE TRIGGER Customer_tru ON dbo.Customer FOR UPDATE
    AS
    BEGIN
         IF UPDATE(CustomerName)
             INSERT dbo.logger (logdate, logmsg) VALUES (DEFAULT, 'dbo.Customer.CustomerName changed')
         IF UPDATE(AddressKey)
             INSERT dbo.logger (logdate, logmsg) VALUES (DEFAULT, 'dbo.Customer.AddressKey changed')
         IF UPDATE(CustomerStatus)
             INSERT dbo.logger (logdate, logmsg) VALUES (DEFAULT, 'dbo.Customer.CustomerStatus changed')
         IF UPDATE(CustomerContact)
             INSERT dbo.logger (logdate, logmsg) VALUES (DEFAULT, 'dbo.Customer.CustomerContact changed')
         IF UPDATE(ContactEmail)
             INSERT dbo.logger (logdate, logmsg) VALUES (DEFAULT, 'dbo.Customer.ContactEmail changed')
    END

    Now, I’ll check the time, then run an update, and select from the logger table. This gives me a nice easy way to see what changes were logged. First, let’s update one field.

    We can see that the change was logged. I could add more info, but this is just a check of what happened.

    2025-05_0227

    Let’s check two changes. We can see that both are detected below.

    2025-05_0228

    Now I’ll update all the fields in a row. There are five other than the PK and I can see all changes logged.

    2025-05_0229

    Note that I’m just detecting an update to this field and marking it as changed. If the value were set to the same value, which some apps do, this is still noted as an update by this trigger. To determine if this value was actually changed, I’d need to compare the inserted and deleted rows.

    That’s a quick look at detecting which fields have changed. In the next post, we’ll look at more information in the trigger.

    SQL New Blogger

    Getting started blogging can be hard. I’m sure many of you have used a trigger. Why not write about setting up a trigger, perhaps with some logic like this. Have you used updated()? Tell us how and why.

    This is a great way to showcase how you approach a problem. This is a basic post here, but I’ve shown above I could do something business related instead of the insert to the logger table.

    This was a 15-20 minute post.

  • Getting References for GenAI Results

    I wrote an editorial on the view of GenAI tech from execs and someone commented that they wanted references for results. Most of us might take a result from a co-worker and use it without asking for any proof of where it comes from. If we trust our co-workers, this can work well. If we don’t, then we might want to know where they learned this and how they know it works.

    For GenAI, we might want some references to help us learn more or check something. Or, more likely, learn how to modify something that isn’t perfect.

    In this sense, GenAI can be better as this gives us the references we need to learn how the answer was generated.

    This post looks at how I got references in a few cases using Claude, Perplexity, and Copilot.

    This is part of a series of experiments with AI systems.

    Asking a Question

    I decided to ask a question that I was asked by someone and I used Copilot to find the answer. Here is my prompt:

    I need to schedule a Powershell script to access a SQL Server and want to use a managed service account to run the script. How can I do this in powershell

    Let’s look at how the various tools I’ve used respond.

    Claude

    Claude.ai is from Anthropic and it’s a tool I’ve enjoyed using. When I pasted in the prompt, I saw this response:

    2025-05_0222

    I got to the bottom and no references, but when I asked for them (see my prompt in the image), I got a few to look at.

    2025-05_0223

    That’s one of the tricks with AI. You can ask it to explain itself.

    Perplexity

    My second test was perplexity, which I started to use a bit after Grant mentioned it.

    2025-05_0220

    Right at the top, I get some references that I can click. When I get to the bottom, I have a list of possible future prompts, which aren’t references, but they get me thinking about things I might need to consider.

    2025-05_0221

    That worked well and I liked having the references, though I’d prefer them at the end.

    Copilot

    I decided to try Copilot inside of VS Code, which is where I’d likely use it. I entered the prompt as a comment in a blank .ps1 file. After my first line, it suggested a few more comments to give context. I accepted a few and then added the last #include references line.

    2025-05_0224

    I didn’t get references and the generation stopped at the #End of script line.

    I then added the comment below asking for URL references.

    2025-05_0225

    Each of the items above appeared as a line in italics, like other suggestions. I hit Tab to accept and I’d get another reference. When I saw the last one repeat, I stopped the responses.

    Summary

    I’m not evaluating the code here, just trying to see if I could get some idea of where the code came from. In this case, I don’t deal with MSAs a lot, so it’s good that I can get some URLs to check docs or get more options other than the code I found.

    If I asked this question on Stack Overflow, I might get the same code (or similar), but getting URLs or references isn’t always easy there. Some people provide them, some don’t, and some might just close my question and say I should have searched better.

    I think the GenAI does a good job here of giving me a starting point, and a place to go, which is helpful.

  • Copilot Outside of SSMS Seems to Work

    I read Brent’s first look at SSMS and Copilot in there. He didn’t have a great opinion of the tool, especially comparing it to Gemini or Claude. I haven’t tested this yet, mostly because I’ve got other stuff going on, but I decided to take his prompt and the code and drop it into the dedicated Copilot App on my Windows 11 laptop.

    This is part of a series of experiments with AI systems.

    I have a button that starts Copilot, so I pressed it and put in this prompt:

    2025-05_line0075

    This was copied from Brent’s post, and then his code copied and dropped in.

    I was curious to see if this worked.

    My Results

    I thought my results were better. The first part of the response is shown below. Copilot sees the scalar function as a problem and rewrites things. I don’t love that this is just the query and not the CREATE OR ALTER PROC part, but still.

    2025-05_line0073

    Below this, it notes that I should test indexes and gives me the ones it would recommend. Then it goes into the fact that order by desc can be problematic. It also has a TOP 1 recommendation for the first query.

    2025-05_line0074

    The rest of the response is OK, and gets into some general things that might help me go past the recommendations.

    2025-05_line0076

    The prompting matters, as if I click on the “what are more perf opt techniques” I get a lot of generic stuff.

    2025-05_line0078

    Is AI going to make you a better DBA or developer? Maybe. It will give you things to think about, but you need to test them. You might even ask a GenAI tool for help on that. I did and got this:

    2025-05_line0079

    And below, some more steps.

    2025-05_line0080

    Not bad, and likely what a lot of people do, though perhaps not with #5, in which HammerDB is suggested to run this proc.

    Learn to use GenAI tools, learn where they help (And save time) and where they can’t be trusted. That’s likely an ongoing battle for most of us, but these tools can help us be more productive.