Since the first post on a related topic, Copilot became available in Microsoft 365, and this opens the door for prompt engineering experiments. A prompt is a "natural language instruction that tells a large language model (LLM) to perform a task" [1], process also known as instruction tuning. Prompt engineering is thus "the process of creating and refining the prompt used by the model" [1].
For example, one can use Prompt Engineering to learn how to perform certain tasks in a programming language like SQL: learning how to define a table, write a query and database objects, etc. In a first experiment I created a set of prompts for creating a set of objects to store and perform CRUD (Create, Read, Update, Delete) operations. The experiment focused on Customer Addresses, Countries, Regions. Let's look at the prompts and their outputs. The following prompts depict the attempts in the order in which they were considered, so feel free to experiment!
Before Copilot, I used macros in Excel or stored procedures to generate similar code. which allowed me to reduce considerably the development time.
Prompt:
Give me the definition of a SQL Server stored procedure for updating
the Customers from the dbo schema based on input parameters
Output:
CREATE PROCEDURE UpdateCustomer @CustomerID INT, @CustomerName NVARCHAR(100), @ContactName NVARCHAR(100), @Country NVARCHAR(50) AS BEGIN UPDATE dbo.Customers SET CustomerName = @CustomerName, ContactName = @ContactName, Country = @Country WHERE CustomerID = @CustomerID; END;
Prompt:
Give me the definition of a SQL Server stored procedure for inserting
Customers in the dbo schema based on input parameters.
Output:
CREATE PROCEDURE InsertCustomer @CustomerName NVARCHAR(100), @ContactName NVARCHAR(100), @Country NVARCHAR(50) AS BEGIN INSERT INTO dbo.Customers (CustomerName, ContactName, Country) VALUES (@CustomerName, @ContactName, @Country); END;
Give me the definition of a SQL Server stored procedure for deleting a Customers from the dbo schema based on Customer Id.
Output:
CREATE PROCEDURE DeleteCustomer @CustomerID INT AS BEGIN DELETE FROM dbo.Customers WHERE CustomerID = @CustomerID; END;
Prompt:
Give me the definition of the SQL Server table used for the above
examples.
Output:
CREATE TABLE dbo.Customers ( CustomerID INT IDENTITY(1,1) PRIMARY KEY, CustomerName NVARCHAR(100) NOT NULL, ContactName NVARCHAR(100), Country NVARCHAR(50) );
Prompt:
Extend the
definition of the previous table with Address information
CREATE TABLE dbo.Customers ( CustomerID INT IDENTITY(1,1) PRIMARY KEY, CustomerName NVARCHAR(100) NOT NULL, ContactName NVARCHAR(100), Country NVARCHAR(50), AddressLine1 NVARCHAR(200), AddressLine2 NVARCHAR(200), City NVARCHAR(100), State NVARCHAR(100), PostalCode NVARCHAR(20) );
Remove the Address information from the above table into a separate Addresses table with the Customer Id as foreign key.
Output:
-- Modified Customers Table: CREATE TABLE dbo.Customers ( CustomerID INT IDENTITY(1,1) PRIMARY KEY, CustomerName NVARCHAR(100) NOT NULL, ContactName NVARCHAR(100), Country NVARCHAR(50) );
-- New Addresses Table: CREATE TABLE dbo.Addresses ( AddressID INT IDENTITY(1,1) PRIMARY KEY, CustomerID INT, AddressLine1 NVARCHAR(200), AddressLine2 NVARCHAR(200), City NVARCHAR(100), State NVARCHAR(100), PostalCode NVARCHAR(20), FOREIGN KEY (CustomerID) REFERENCES dbo.Customers(CustomerID) );
Prompt:
Create a Countries table that can be referenced from the Addresses
table with Country ISO codes.
Output:
--Create the Countries Table: CREATE TABLE dbo.Countries ( CountryCode CHAR(2) PRIMARY KEY, -- ISO 3166-1 alpha-2 code CountryName NVARCHAR(100) NOT NULL ); --Modify the Addresses Table: CREATE TABLE dbo.Addresses ( AddressID INT IDENTITY(1,1) PRIMARY KEY, CustomerID INT, AddressLine1 NVARCHAR(200), AddressLine2 NVARCHAR(200), City NVARCHAR(100), State NVARCHAR(100), PostalCode NVARCHAR(20), CountryCode CHAR(2), FOREIGN KEY (CustomerID) REFERENCES dbo.Customers(CustomerID), FOREIGN KEY (CountryCode) REFERENCES dbo.Countries(CountryCode) );
Prompt:
Extend the Countries table with ISO 3 characters code and ISO Number.
Output:
CREATE TABLE dbo.Countries ( CountryCode CHAR(2) PRIMARY KEY, -- ISO 3166-1 alpha-2 code CountryName NVARCHAR(100) NOT NULL, ISO3Code CHAR(3), -- ISO 3166-1 alpha-3 code ISONumericCode INT -- ISO 3166-1 numeric code );
Prompt:
Create a Regions table with Region code and description that allows
to group the countries in territories. A country can be assigned to
multiple regions.
Output:
-- Create the Regions Table: CREATE TABLE dbo.Regions ( RegionCode CHAR(3) PRIMARY KEY, RegionDescription NVARCHAR(100) NOT NULL ); -- Create the Countries Table (including the previous columns): CREATE TABLE dbo.Countries ( CountryCode CHAR(2) PRIMARY KEY, -- ISO 3166-1 alpha-2 code CountryName NVARCHAR(100) NOT NULL, ISO3Code CHAR(3), -- ISO 3166-1 alpha-3 code ISONumericCode INT -- ISO 3166-1 numeric code ); -- Create the CountryRegions Junction Table: CREATE TABLE dbo.CountryRegions ( CountryCode CHAR(2), RegionCode CHAR(3), PRIMARY KEY (CountryCode, RegionCode), FOREIGN KEY (CountryCode) REFERENCES dbo.Countries(CountryCode), FOREIGN KEY (RegionCode) REFERENCES dbo.Regions(RegionCode) );
Prompt:
Create a view based on Customers that includes all the above tables
Output:
CREATE VIEW CustomerDetails AS SELECT c.CustomerID, c.CustomerName, c.ContactName, a.AddressLine1, a.AddressLine2, a.City, a.State, a.PostalCode, co.CountryCode, co.CountryName, co.ISO3Code, co.ISONumericCode, r.RegionCode, r.RegionDescription FROM dbo.Customers c LEFT JOIN dbo.Addresses a ON c.CustomerID = a.CustomerID LEFT JOIN dbo.Countries co ON a.CountryCode = co.CountryCode LEFT JOIN dbo.CountryRegions cr ON co.CountryCode = cr.CountryCode LEFT JOIN dbo.Regions r ON cr.RegionCode = r.RegionCode;
Prompt:
In the above view use 3 letter encoding for table's name
Output:
CREATE VIEW CustomerDetails AS SELECT cus.CustomerID, cus.CustomerName, cus.ContactName, add.AddressLine1, add.AddressLine2, add.City, add.State, add.PostalCode, cou.CountryCode, cou.CountryName, cou.ISO3Code, cou.ISONumericCode, reg.RegionCode, reg.RegionDescription FROM dbo.Customers cus LEFT JOIN dbo.Addresses add ON cus.CustomerID = add.CustomerID LEFT JOIN dbo.Countries cou ON add.CountryCode = cou.CountryCode LEFT JOIN dbo.CountryRegions cr ON cou.CountryCode = cr.CountryCode LEFT JOIN dbo.Regions reg ON cr.RegionCode = reg.RegionCode;
Unfortunately, the definition uses the "add" reserved word for addresses as prefix. Therefore, the following prompt:
Prompt:
Modify the
above view to use 3-letter aliases that aren't as reserved words
Output:
CREATE VIEW dbo.CustomerDetails AS SELECT cus.CustomerID, -- Customer ID cus.CustomerName, -- Customer name cus.ContactName, -- Contact name adr.AddressLine1, -- First line of the address adr.AddressLine2, -- Second line of the address adr.City, -- City of the address adr.State, -- State or region of the address adr.PostalCode, -- Postal or ZIP code of the address cou.CountryCode, -- Country code cou.CountryName, -- Country name cou.ISO3Code, -- ISO 3166-1 alpha-3 code cou.ISONumericCode, -- ISO 3166-1 numeric code reg.RegionCode, -- Region code reg.RegionDescription -- Region description FROM dbo.Customers cus LEFT JOIN dbo.Addresses adr ON cus.CustomerID = adr.CustomerID LEFT JOIN dbo.Countries cou ON adr.CountryCode = cou.CountryCode LEFT JOIN dbo.CountryRegions cr ON cou.CountryCode = cr.CountryCode LEFT JOIN dbo.Regions reg ON cr.RegionCode = reg.RegionCode;
Modify the schema of the above objects to include the schema name.
Prompt:
Change the definition of the above tables and test whether the
tables already exists.
Prompt:
Annotate the definition of the above objects with a comment.
Prompt:
Generate the scripts for inserting 10 customers with different
addresses in the above tables.
Prompt:
Aggregate the update and insert commands into the same stored
procedure.
Output:
CREATE PROCEDURE dbo.UpsertCustomer @CustomerID INT = NULL, -- Optional parameter for insert @CustomerName NVARCHAR(100), @ContactName NVARCHAR(100), @Country NVARCHAR(50) AS BEGIN IF EXISTS (SELECT 1 FROM dbo.Customers WHERE CustomerID = @CustomerID) BEGIN -- Update existing customer UPDATE dbo.Customers SET CustomerName = @CustomerName, ContactName = @ContactName, Country = @Country WHERE CustomerID = @CustomerID; END ELSE BEGIN -- Insert new customer INSERT INTO dbo.Customers (CustomerName, ContactName, Country) VALUES (@CustomerName, @ContactName, @Country); END END;
I used to create similar code in the past to consolidate the logic for inserts and updates within the same stored procedure. This allows to reduce the number of objects created in a database and minimize the impact of some other issues (e.g. code duplication for validation).
I also use the comma before each line of text where it applies (and not at the end). However, this can be addressed with the following prompt:
Prompt:
Rewrite the above database objects by butting the comma in front of
each line where it applies.
Prompt:
Modify the view so each join condition is written on its own line.
Prompt:
Modify the view with create or alter command.
Prompt:
Modify the view to check for null values.
Comments:
1) I could use the scripts also in a SQL database, though one
must pay attention to the order in which the steps must be run.
2)
All these are basic steps; so, a natural question: how far can we go? One
can generate further objects, and knowledge about the data model seems to
be available in Copilot, though normal data models are much more complex
than this! Probably, there's a limit beyond which Copilot will start to be
inefficient as long the data model is not available explicitly. SQL Server
Copilot would help probably to overcome such limitations, though the
feature is still in limited preview.
3) I wonder whether given a set
of best practices, Copilot will be able to use them and create the CRUD
objects accordingly. More experiments are needed though.
4) It will
be interesting to observe how much the prompts generated by other people
lead to similar or different outcomes. (I observed that nontechnical
prompts generated in the past different outcomes.)
5) The fact that I
was able to change some formatting (e.g. comma before each line) for all
objects with just a prompt frankly made my day! I can't stress enough how
many hours of work the unformatted code required in the past! It will be
interesting to check if this can be applied also to a complex database
schema.
Happy coding!
Previous Post <<||>> Next Post
References:
[1] Microsoft 365 (2024) Overview of prompts [link]
Resources:
[R1] Microsoft 365 (2025) Microsoft 365 Copilot release notes
[link]
[R2] Microsoft 365 (2025) What’s new in Microsoft 365 Copilot |
Jan 2025 [link]
[R3] Microsoft 365 (2025) Copilot is now included in Microsoft 365
Personal and Family [link]
Acronyms:
LLM - large language model
CRUD - Create, Read, Update, Delete
No comments:
Post a Comment