Tag: syndicated

  • A New Word: Lackout

    lackout – n. the sudden awareness that you’re finally over someone, noticing that the same voice that once triggered a cocktail of emotions now evokes nothing at all – as if your brain had returned the last box of their things and your heart had quietly changed its locks.

    I think I’ve learned to have more lackout as I get older. Perhaps things impact me less or I judge less importance, but I find myself letting go of hard/sad/angry/disappointed/jealous/etc. negative feelings towards people much quicker, with lackout occurring sooner after an event.

    Certainly this can happen with romantic relationships, though I think a lot of us never get over things and prefer not to see exes.

    However, I’ve had that happen at work, where I am upset with someone, and I don’t want to hear their voice, or correspond in email, or even shake their hand. No hugs for sure.

    The thing I’ve learned to do is let things go. Maybe one of the things I let go, which was public, was not being allowed on the ballet for the PASS Board of Directors. I was very upset with the committee, who I think let personal feelings get in the way of making a decision. I was quite angry with that group of people for a long time.

    A few years.

    However, I’ve seen a few since then and been not only civil, I find myself with lackout, having let that anger go.

    Life is better without anger or grudges.

    From the Dictionary of Obscure Sorrows

  • Generating Random Strings with GenAI

    One of the things I’ve been experimenting with in AI is taking things other people do and seeing how well the AI works. In this case, I took a Prompt from Louis and tried to see how well it worked. This post describes the results from a few models.

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

    The Challenge Using Claude

    Louis was using an AI to generate some test data to play with the new Regex functionality in SQL Server 2025. He put this in ChatGPT: “create a set of random string data with 1000 rows for a sql server table named RegExTest. It should insert data into a column named Value”.

    He had mixed results with ChatGPT, which I tend not to use. Instead, I tried this in Claude. I like Claude as I get an explanation separate from the code. Here’s a view of the page:

    2025-06_line0031

    Here’s the code, which is nice because I could steal certain patterns out of here if I had the need. The explanation was also good, and I’ve reproduced that here:

    <start claude explanation>

    This SQL script creates 1000 rows of diverse random string data for your RegExTest table. The data includes various patterns that are useful for testing regular expressions:

    • Email addresses (user@domain.com)
    • Phone numbers ((123) 456-7890)
    • Dates (MM/DD/YYYY)
    • Mixed alphanumeric with special characters (ABC-123_XYZ)
    • Numeric strings (123456)
    • URL patterns (https://www.example.com/path)
    • Code patterns (AB12C345)
    • Words with spaces (Hello World)
    • Mixed case strings (AbCdEf123)
    • Random alphanumeric strings

    The script uses a recursive CTE to generate 1000 rows and applies different string generation patterns based on the row number modulo operations. This ensures you get a good variety of data types to test your regular expressions against.

    The script also includes table creation (if it doesn’t exist) and verification queries to confirm the data was inserted successfully.

    <end claude explanation>

    There was an issue in the else part of the CASE. The last CONCAT call only had the first parameter and CONCAT needs two parameters, so I copy/pasted the 2nd parameter from the last THEN statement, which worked fine. In this case, that parameter was an acceptable choice to create a random alpha string.

    Perplexity

    I got a very weak result from Perplexity. Essentially, write insert statements, though you could use a script.

    2025-06_line0037

    I didn’t see a script, so I asked. I got this.

    2025-06_line0039

    Here’s the SQL Code:

    2025-06_line0040

    That’s weak. It works, but it’s weak and I think I could have written that in not much more time than the AI took.

    It did end with this sentence: Let me know if you want the script in another format or with different string lengths!

    I did and then got a series of different scripts for different formats, but each was producing a separate 1000 rows of only that format.

    DeepSeek

    I download the DeepSeek coder model and decided to try that. The basic prompt was disappointing. The model basically wanted to use Python and only imported modules without other code.

    2025-06_line0041

    When I said that and asked for code, I got more details, but with the script separated out into sections. The top seemed to repeat a bit.

    2025-06_line0042

    Then I got each part of the script.

    2025-06_line0043

    I didn’t run this, but it’s a reasonable way to do things for developers. For data people, this seems like overhead.

    I asked for SQL, and got a script for Oracle, but more interesting, the code is for 1000 rows, but the comments say ten thousand. Can’t the GenAI count?

    2025-06_line0044

    I asked to change this to SQL Server and got this code.

    2025-06_line0045

    I don’t know what to say except that I’m disappointed in the local deepseek model, which is not only slow, but hasn’t produced a good answer.

    Summary

    Claude clearly wins this experiment.

  • Heading to SQL Bits 2025

    I’ll be at SQL Bits tomorrow, Saturday Jun 20, 2025 for the final day of the conference. I wasn’t selected to speak, but since I’m in Cambridge next week I came a couple of days early to stop by the event.

    As this publishes, I’m probably just about to land at Heathrow and I am looking forward to a fairly quiet day in London.

    Tomorrow should be fun. I have lightly looked at the schedule and I see a few AI sessions that might be fun to watch, but mostly I’m looking forward to catching up with friends.

    If you see me, please don’t hesitate to say hi.

  • Better Trigger Design: #SQLNewBlogger

    I had someone ask me about using triggers to detect changes in their tables. This is the third post in the series. The first one

    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 first post.  This is the dbo.Customer table with a PK and 5 other fields. Here is the data in the table:

    2025-05_0231

    I had this trigger in the last post, and showed how it captured updates to the ContactEmail field.

    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 seemed to work, but did it really?

    The Problem

    Let’s illustrate the big problem with this change. I’ll run this code:

    UPDATE dbo.Customer
      SET ContactEmail = ‘andy@sqlservercentral.com’
      WHERE CustomerID = 2;

    If I do this, here are the results:

    2025-05_0232

    I get a NULL? Why, the original value is null and when I concatenate null with other values, I get NULL. Not ideal.

    Let’s fix this problem. I’ll use a function to handle null values. Note, I need to do this for both the inserted and deleted tables. Here’s the new trigger.

    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 ' + COALESCE(d.ContactEmail, 'null') + ' to ' + COALESCE(i.ContactEmail, 'null')
              FROM inserted i
              INNER JOIN Deleted d ON i.CustomerID = d.CustomerID
         END
    END

    We can see this handles the null appropriately.

    2025-05_0233

    In this case I’ve chosen to replace a NULL value with the word ‘null’. This means something to me, but I could have just as well replaced this with “blank” or any other word. In many applications a developer might display a null value as a blank, so choose what works for you.

    I’m also including an example to show this works for multiple rows. Here I’ll update multiple rows and we can see each is inserted into my log.

    2025-05_0234

    This is a good reason to audit certain activities, as people will sometimes make these mistakes and updates lots of data.

    This trigger is slightly more useful, and handles the NULL cases, but it still isn’t perfect. Imagine I need to parse out changes, or generate the reverse transactions, or even search for certain changes. Stuffing a lot of data into a single field is overloading it, and making it less useful over time. What we’d really want to do is separate pertinent data into different fields. In a NoSQL world, we might do this by using a JSON schema to track the before and after.

    We could do that here, just stuff JSON into the log message and read it back out and de-serialize it.

    SQL New Blogger

    This post modified our trigger to address a previous design problem: not handling nulls. We also showed how to test the trigger with multiple rows. This shows I’ve added knowledge to my skillset and can test what I’m trying to do.

    Write your own blogs that might examine what you’ve done poorly in the past and how to fix the problems you’ve identified, even in simple code. Many of us do this a lot.

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