Tag: SQLNewBlogger

  • Modifying a Trigger to Capture More Info: #SQLNewBlogger

    I had someone ask me about using triggers to detect changes in their tables. This is a second post looking at triggers, in this case, modifying my trigger to detect more changes and using that information.

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

    The Setup

    We’re using the same table from the last post.  This is the dbo.Customer table with a PK and 5 other fields.

    In this case we want to track the changes to an email and capture what those changes are. In other words, if I update the email from ‘sjones@sqlservercentral.com’ to ‘steve.jones@red-gate.com’, I want to capture

    To do this, let’s modify our trigger. We can still test if the field is updated with UPDATE(). We did this in the last post.

    This will let us know that the column changes by returning a boolean. If this is true, we want to insert the new values into our logger. We also want to capture the old value. These values are stored in the inserted and deleted tables, which are available in a trigger. I’ll use a join between these on the PK to get the same data from both.

    I’m also using a query with these tables because more than one row can be updated and we want to capture all the changes.

    Here is my new trigger, with the OR ALTER added to the code.

    CREATE OR ALTER 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)
         BEGIN
             INSERT dbo.logger (logdate, logmsg) 
             SELECT GETDATE(), 'ContactEmail updated from ' + d.ContactEmail + ' to ' + i.ContactEmail 
              FROM inserted i
              INNER JOIN Deleted d ON i.CustomerID = d.CustomerID
         END
    END

    This is mostly the same code, but now I’ve changed the last conditional test. If the email is updated, I want to query the inserted and deleted tables and create a log message. This is the type of thing I’ve seen often in systems, and while it’s not a great pattern, it does let me capture some information. There are some problems with this, I’ll discuss in the next post.

    We can see below that when I run this code, I get the updated captured and logged.

    2025-05_0230

    This post has introduced a few new things, the inserted and deleted tables, which I didn’t discuss in the last post. However, they are useful when you want to capture information affected in triggers, which can be more than one row. Using these tables helps you set up triggers that handle multiple changes.

    There are problems with this trigger, mainly with NULLs, potential performance, and architecture in what is captured, but we’ll address those in the future.

    SQL New Blogger

    This post looks at enhancing a previous post and providing more information. You (hopefully) learn from your work, from both feedback  and experiments, and you should modify your thinking and work. This shows how I’ve adapted something I did previously, which is a skill we all need.

    This was a 20-30 minute post for me. You could likely do it in a similar amount of time.

  • 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.

  • Create a Linked Server: #SQLNewBlogger

    I had a customer recently that was asking about Linked Servers and some development advice. I was going to show them a few things and realized I hadn’t created a linked server in my demo environment, so I did it and decided to create a quick post on this.

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

    The Scenario

    I have a few demo instances of SQL Server in my local environment: Aristotle and Aristotle\SQL2022. In this case I was connected to the named instance, and decided to create a connection to Aristotle. As you can see, I don’t have any linked servers in the named instance.

    2025-04_0125

    To create a linked server, I can use this simple code:

    EXEC master.dbo.sp_addlinkedserver   
         @server = N'Aristotle',   
         @srvproduct=N'SQL Server';  
    GO

    This creates the linked server (as you can see below), with a number of defaults. In this case, the security is made with whatever login queries the linked server.

    2025-04_0126

    You can see the security properties here:

    2025-04_0127

    This might be OK in your enviroment, or it might not be. Perhaps you need to ensure everyone querying the remote server uses the same login. In which case, the sp_addlinkedserver procedure doesn’t do this. You would need to use sp_addlinkedsrvlogin to do that. That’s for another post.

    NOTE: Be sure you understand what a linked server does, how to use it, and the downsides. There are many and this can slow down your application or overload servers

    I can test this connection by right clicking the Linked Server in SSMS:

    2025-04_0128

    This works, as expected.

    2025-04_0129

    I can also run a query through the linked server, using 4-part naming with the linked server, then the database, schema, and table. This also works:

    2025-04_0160

    That’s it to get started. I recommend you be careful when using linked servers as this creates a bit of a tight coupling and makes development harder. I might recommend you get away from querying database server to database server when possible and let an application do this work if it’s possible.

    SQL New Blogger

    Linked Servers aren’t that common, but they aren’t rare. This is a skill that SQL Server people should have and understand a bit about. This post is very basic, but it provides a jumping off point where I could write a number of other posts related to linked servers and perhaps guide an interviewer along a path of asking me about them. I certainly showcase some knowledge here if someone asks me if I’ve ever created one.

    This post took me about 10 minutes to test and write, and you could probably do this in your environment. You don’t even need to servers, as you could create a loopback linked server.

  • Can I Change a Primary Key Value? #SQLNewBlogger

    I heard someone say recently that you can’t change a primary key value in a row. That’s not the case, so I decided to show a quick proof of that.

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

    The Scenario

    Let’s set up a simple table with some data.

    CREATE TABLE PKChangeTest (
    ImportantNumber VARCHAR(20) NOT NULL CONSTRAINT PKChangeTestPK PRIMARY KEY
    , CustomerName VARCHAR(50)
    , StatusValue INT)
    GO
    INSERT dbo.PKChangeTest
       (ImportantNumber, CustomerName, StatusValue)
    VALUES
       ('1234567', 'Steve', 1)
    ,  ('2345678', 'Andy', 1)
    ,  ('3456789', 'Brian', 1)
    ,  ('1235667', 'Leon', 1)
    ,  ('1265567', 'Dave', 1)
    ,  ('9914567', 'Bill', 1)
    GO

    If I look at this table, I have some unique numbers making up the PKs. If I select from the table, I can see the data.

    2025-04_0117

    Now, let’s change some data. I’ll change the PK values with a few statements. Then I’ll select from the table, and we will see things changed.

    2025-04_0118

    The ImportantNumber for both Bill and Steve have changed. These are PK modifications.

    We can change a PK value. These are not set in stone once inserted.

    SQL New Blogger

    This is a short look at something that’s a myth among some people. When I heard someone say this, I knew I needed to prove this. The scenario took just about 5 minutes to set up (even without AI), and then it was another 10 minutes to structure and write this post.  I actually have 2 more ideas from this on things I can show to prove how PKs work and are malleable.

    You can do the same thing. When you wonder about something, or hear something that isn’t true from others, prove it. And blog about it.