SQL Server Stored procedure in Power AppsSQL Server Stored procedure in Power Apps

Recently Microsoft released a new feature in the ultimate Power Apps user guide that will let you call SQL Stored procedures without needing to call a flow in Power Automate

run SQL Upcoming
run SQL Upcoming

What are SQL Server Stored Procedures?

A Stored Procedure is nothing more than a piece of code that will do something within your database. Well that is a great description!

The above mentioned feature links to Make direct calls to SQL Server stored procedures on Microsoft Learn. This article however isn’t much help if you want to get started with making your Power Apps solutions communicate faster with your data.

Maybe we should look at an example. Imagine that we have a table with cars and we want to select all cars that have a specific colour. The following procedure would do this give us an option to specify a colour and the required car records would be returned.

CREATE PROCEDURE PROC_GetColourCars
(
-- Add the parameters for the stored procedure here
@SelectedColour nvarchar(256) = NULL
)
AS
BEGIN

SELECT *
FROM Cars
WHERE Colour = @SelectedColour
END
GO

Typically we would want to ask the user of an app to supply the colour and then get the stored procedure to return the relevant records to us.

Why would you use SQL Server Stored Procedures?

There are a few of reasons but the main reasons will be

  • Performance
  • Hiding complexity from your app
  • Reliability and efficiency of the app

The above example was simple of course, but how about if we wanted to read data form multiple tables or if we wanted to update specific records or if we wanted to do anything else that we could easily do with SQL.

Dataverse or SQL Server

Of course, from a Power Platform perspective I would always prefer to use SQL Server, but if you have data that lives in SQL Server, why would you want to copy that between two different locations. You might as well access data where it currently resides rather than moving it all the time to ensure that two databases are always up to date.

To use SQL Server connections in Power Apps, we just add a connection to our app and now we can use data from the table that we selected.

Data source with SQL Server Table

But how do we use Stored Procedures?

Creating SQL Server Stored procedures connections in Power Apps

So how can add a stored procedure as a datasource?

Like with the tables we select SQL Server

How to Run SQL Server stored procedures in Power Apps without Power Automate in 2024 Microsoft Power Apps, Microsoft SQL Server w8iNJOroFU7jAAAAABJRU5ErkJggg==

Then you can select either a Dataset or create a new dataset:

Choose a dataset

First make sure that you have enabled the preview feature.

SQL Server stored procedure feature

Now when you have enabled the preview feature to call SQL Server stored Procedures you will notice the Stored procedure tab:

Choose a table

In the Stored Procedures we will find our stored procedure that we created earlier in out SQL Server Database.

Select a stored procedure from SQL

Once we select the stored procedure we have to make an additional choice. Is this Stored Procedure safe to use in galleries and tables?

So for example, if you used this stored procedure and it does updates to tables, would you want this procedure to run within a gallery? Probably not. Unless of course you wanted to audit users accessing data.

stored procedure listed as a datasource

Ok, now we have a connection called after my database. Hmm, this could be confusing. WE better have a look at how this is going to work. Maybe Power Apps is going to surprise us. It looks like the connection asks us for one or more stored procedures. And we can access it through as database object. That looks quite nice and clean!

Calling SQL Server Stored procedures in Power Apps

I created a little demo app. (Yes, it doesn’t look good and wouldn’t pass my QA tests). On the top left I can add cars. On the right I’m listing all cars in my table.

In the Items property of my gallery, displaying the Green cars, I only have to use the following line of code.

sqldemo.dboPROCGetColourCars({SelectedColour: TextInput2.Text}).ResultSets.Table1

At the bottom left I can filter by colour. And my gallery will show just the Green cars.

Stored procedure called from Power Apps

So now we have the option to populate galleries using data returned by the very efficient stored procedures in SQL Server. This will reducing the complexity of your app and make the data traffic between your app and your database more efficient.

Limitations

So far one of the limitation that I have found is that stored procedure cannot be called using the Mobile Power Apps app. Running a stored procedure on a mobile app results in “Resource not found” error messages.

SQL Stored Procedures on a mobile report: Resource not found
SQL Stored Procedures on a mobile report: Resource not found

Another thing to be aware of is that when you add additional stored procedures to your app, from the same database, you might want to remove the existing connection first. Otherwise you might end up with multiple connections as shown below.

Avatar for Pieter Veenstra

By Pieter Veenstra

Business Applications Microsoft MVP working as the Head of Power Platform at Vantage 365. You can contact me using contact@sharepains.com

32 thoughts on “How to Run SQL Server stored procedures in Power Apps without Power Automate in 2024”
  1. Can you provide the screenshot of the snippet how u accessed the stored procedure in powerapps. I mean how to access the data returned from stored procedure and displaying that data into galleries. I was able to connect to the stored procedure. But in the items property of gallery If I am trying to access it, it is throwing error. i tried accessing it as databasename.storedprocedure

      1. Table1 does apear when I run the app monitor but does not work in code. Does not seem to recognise Table1.

      2. Hi Mark,

        It sounds like your stored procedure might not be returning data.

        This could be down to the Stored Procedure not working properly. Could this maybe be permission related? Can you check if your stored procedure is actually called or not.

      3. Records from the SP do appear in the Monitor – I can see multiple records in the JSON output. I think it’s not loading into the collection due to an undefined type. In other ways I’m finding these SP quite buggy – like the fact they work in design mode but not consistently when used from a mobile in runtime.

      4. The Stored Procedures feature is still in preview. So far I’ve not had any issues with them. Even when I get a Stored procedure to return no data, I’m still seeing a table coming back.

        Both in the published version of the app as well as the app in studio mode, I’m not seeing any issues at all.

        Can you send me a screenshot of the error on the chat?

      5. Hi Pieter, I’ve solved my other issue with some SPs failing on a 403 error. I had to “Disable secure implicit connections” – a RETIRED setting under Upcoming features. I’m wondering if the reason you can load resultsets into a collection and I can’t is due to some other obscure setting. Possible candidates to compare:

        Preview: Explicit column selection
        Retired: Allow automatic field assignment for component inputs

        What values are you using for those settings?

  2. Thanks for sharing this new update. It’s exciting!
    Can you share how to handle the returned data from stored procedure? Yes, i was able to make the call successfully, but the returned data is Untyped.
    I can only do Set(colTest, TestDb.dbosppaGetOpenProjectItems().ResultSets.Table1) instead of ClearCollect(colTest, …). PowerApps doesn’t recognize that the returned data is of type records?
    Next, I want to display colTest in gallery. I set the item property to colTest, but got an error: Expected table value.
    How do i cast colTest to a table type or how to handle it so i can use the data in my app?
    Thanks!

      1. Hi Tina, Thank you for sending through the details. In Power Apps, you can call the stored procedure once you have added it as a datasource with .ResultSets.Table1 after the stored procedure call. This will give you the same data structures that you have seen in Power Automate in the past.

      2. Pieter, this is fantastic!
        I’m receiving the same message as Tina. I created a sproc and gave a login Execute rights to the procedure.
        I use the procedure in a gallery in Items by calling IT_SPT.dbospstudentsearch({searchText: TextInput1.Text}).ResultSets.Table1 and I receive the old “expected a table value” message.
        Are there permissions issues somewhere that I could be missing?
        Here is my procedure:
        ALTER PROCEDURE [dbo].[sp_student_search]
        (
        @searchText NVARCHAR(256) = NULL
        )
        AS
        BEGIN
        SELECT DISTINCT
        stu.studentNumber AS PERMNUM,
        stu.personid,
        stu.lastName AS LASTNAME,
        stu.firstName AS FIRSTNAME,
        ISNULL(LEFT(stu.middleName, 1), ”) AS MI,
        stu.GRADE AS GRADE,
        C.CaseID,
        C.ScholasticYear
        FROM
        X.Y.dbo.students AS stu
        LEFT OUTER JOIN
        X.infinite.dbo.Zsh ON stu.personid = sh.StudentPersonID
        LEFT JOIN Cases C ON stu.personID = C.StudentID
        WHERE
        stu.activeYear = 1 AND stu.activeToday = 1
        AND stu.schoolNumber IN (1, 2, 3)
        AND (
        (ISNUMERIC(@searchText) = 1 AND C.CaseID = CASE WHEN ISNUMERIC(@searchText) = 1 THEN CAST(@searchText AS INT) ELSE NULL END)
        OR
        (ISNUMERIC(@searchText) = 0 AND UPPER(stu.lastname) LIKE ‘%’ + UPPER(@searchText) + ‘%’)
        );
        END
        GO

      3. Hi Steve,

        Can you check if your stored procedure is actually called? It looks like it isn’t returning back to the app. Could this be permission related?

        Can you check at the SQL end if the procedure is being called at all?

      4. Hi Pieter,
        Thanks for your time. However, I am afraid that i am still not on the same page with you.
        I made a demo app and record a short video on the issue I have. Could you please check: https://www.youtube.com/watch?v=SLYiomBWitY
        Questions:
        1. How do you store the data returned from the SQL store procedure? In collection?
        2. The returned data is untyped. How do you handle it?

        Thanks!

      5. Hi Tina,

        You can add it directly to a gallery, or you can add it into a collection. Either way works fine for me.

        When you created the connection to the Stored procedure did you tick the box that the data is suitable for galleries and tables?

      6. Hi Pieter,

        Yes, I did tick the box that the data is suitable for galleries and tables. I also tried to set TestDb.dbosppaGetInventory().ResultSets.Table1 directly in the gallery’s item property. But still…the issue persists. It still says “Expect Table Value”.

  3. Pieter, this is fantastic!
    I’m having an issue with the permissions for the procedure.
    I created a new SQL Server connection (using SQL Authentication) and granted that login Execute access to the procedure.
    I’m getting the same message as Tina when I include this in Items for my gallery: IT_SPT.dbospstudentsearch({searchText: “Smith”}).ResultSets.Table1. It’s saying that it is expecting a table value.
    ALTER PROCEDURE [dbo].[sp_student_search]
    (
    @searchText NVARCHAR(256) = NULL
    )
    AS
    BEGIN
    SELECT DISTINCT
    stu.studentNumber AS PERMNUM,
    stu.personid,
    stu.lastName AS LASTNAME,
    stu.firstName AS FIRSTNAME,
    ISNULL(LEFT(stu.middleName, 1), ”) AS MI,
    stu.GRADE AS GRADE,
    C.CaseID,
    C.ScholasticYear
    FROM
    X.Y.dbo.students AS stu
    LEFT OUTER JOIN
    A.B.dbo.StudentHomeHistory sh ON stu.personid = sh.StudentPersonID
    LEFT JOIN Cases C ON stu.personID = C.StudentID
    WHERE
    stu.activeYear = 1 AND stu.activeToday = 1
    AND stu.schoolNumber IN (1, 2, 3)
    AND (
    (ISNUMERIC(@searchText) = 1 AND C.CaseID = CASE WHEN ISNUMERIC(@searchText) = 1 THEN CAST(@searchText AS INT) ELSE NULL END)
    OR
    (ISNUMERIC(@searchText) = 0 AND UPPER(stu.lastname) LIKE ‘%’ + UPPER(@searchText) + ‘%’)
    );
    END
    GO

    1. Hi Steve,

      For a temporary solution, you can manually cast the untyped record value into the desired type and map the records into a new collection that galleries recognize.
      This is a temporary solution until this new feature stablilze.

      Step1: Get untyped data from stored procedure.
      Set(colTest, TestDb_1.dbosppaGetInventory().ResultSets.Table1);

      Step2: Convert an array of records to a typed table .
      ClearCollect(
      colInventory,
      ForAll(
      colTest,
      {
      PartNumber: Text(ThisRecord.PartNumber),
      CurrentInventory: Value(ThisRecord.CurrentInventory),
      AllocatedInventory: Value(ThisRecord.AllocatedInventory),
      BinNumber: Text(ThisRecord.BinNumber)
      }
      )
      );

      Step3: Use collection colInventory to display data.

      1. @Tina – perfect. This solves the problem of getting the untyped ResultSet from the stored procedure into a collection. In my version I just nested the SP call inside the ForAll to avoid creating a global collection:

        ClearCollect(
        colJSA,
        ForAll(
        TaskJSA_SEL.entTaskJSASEL(
        {
        IncludeRS: 0,
        OutputAllColumns: 1,
        TaskID: 202202
        }
        ).ResultSets.Table1,
        {
        ID: Value(ThisRecord.ID),
        Display: Value(ThisRecord.Display),
        Seq: Text(ThisRecord.Seq),
        TaskID: Value(ThisRecord.TaskID),
        CustomerName: Text(ThisRecord.CustomerName),
        LocationName: Text(ThisRecord.LocationName),
        RequiredPPE: Text(ThisRecord.RequiredPPE)
        }
        )
        );

        For some reason Pieter seemed to not need the explicit typing of the columns of the ResultSet, hopefully he can update his article to cover this.

      2. So far I haven’t managed to figure out why it just works for me. Maybe it is that my simple example was just a “select *” returning a table. This is easy to understand by Power Apps. If you have an output with a less clear schema then maybe you end up with unformatted data. I will do some more testing over the next few days.

      3. Hi Pieter, most of my stored procedures are doing complex operations on the server and then returning some resultant data set. It would seem that “typing” the ResultSets.Table1 columns is the best solution until the Power Platform gets this ability natively. Note: if you use Value() instead of Text() for a text column then the column just shows “?” in place of that column and the rest of the record is imported.

        Stored Procedures can return multiple result sets. I tested this but did not get any data in the second collection. The Monitor tool shows the JSON “Response” with only 1 table, Table1, so I guess multiple recordsets are not supported yet. The Response also contains a node for OutputParameters but I suspect this is not supported either.

        Yesterday I decided to try Table Valued Functions since these have a defined table structure as part of the definition, and they appear in the list of procedures when adding the connection ….. but they don’t work. It might be because TVF’s don’t use named parameters whereas PowerApps requires named parameters.

  4. Hey everyone, thanks for trying things out and leaving details about what is going on. If you would like to contact me directly (lanced@microsoft.com) I’d be happy to work with you directly to make sure that things are working. A couple of notes. 1.) a fix to support return types and output variables has been submitted for code review. I expect it to be out in a couple of weeks. 2.) In the documentation you will note that I use Power Apps variables to capture the SP call. This could be missed. But, galleries don’t work with direct invocations of actions. Assigning to a variable gets us a table object that can be worked with.

    https://powerapps.microsoft.com/en-us/blog/call-sql-server-stored-procedures-directly-in-power-fx-preview/

    1. Thanks Lance – that is good news. “Typing” the columns of the output will save a lot of work and output parameters will enable error handling and other logic.
      Can I suggest that TVF’s should be excluded from the list of Stored Procedures until such time as they are provisioned.
      Also, with each new stored procedure a new data table is created, and it gets its name from the SQL Database name. Inside it is the name of the stored procedure and it’s available with intellisense : DatabaseName.sprocname . However, the next procedure you add is called DatabaseName_1. So, it’s important to always rename the data table so you can tell which one is which. If the data table name was the same as the stored procedure that would tidy things up and not require the extra step of renaming.

    2. Thank you Lance – this functionality is a game-changer! Please will you share an update here when output parameters and TVFs are working?

  5. And, we know about the issue with secure implicit connections. That fix is also on the way. The reason I use a variable with galleries is because you can’t otherwise update the gallery once you update a value. If you use a variable then you can “reset” it in the code you use for an update, submit, or delete button.

  6. After some stored procedure connections started to return error 403 I tried various ways to get them going again. I have found that a connection can be working one day and the next morning it’s still working … but … after making a few changes to just the GUI of the app the connections fail with error 403. To fix this I take the following steps:

    1. delete the old procs eg dbo.myprocA and dbo.myprocB

    2. remove the data sources for those procs from the app

    3. re-create the procs but this time with the suffix “1” in the name of the proc: eg dbo.myprocA1 and dbo.myprocB1

    4. restart the gateway – if you miss this step you will see error 400 for a few hours till the gateway catches up the cloud fully.

    5. reconnect the data sources to the new procs. NB: connecting more than 1 proc at a time will give you 1 data source with both procs under it. Rename the datasource to say “sqldb” and refer to the procs as sqldb.myprocA1 and sqldb.myprocB1

    6. save and publish the app

    7. NB: when saving/publishing the app I increment a version number on the home screen so I can see it has ACTUALLY updated when I go to test it. Sometime even waiting a few minutes and restarting the app (and loading the “new” version) actually just runs the old version. Much confusion if trying to test something and you’re still running the old version!!

    There are 4 issues I see that need resolving:

    1. There seems to be a bug where a perfectly fine call to a stored procedure will, at some point, start throwing error 403. The steps above will fix it, repeatably, each time. I spent a good 8hrs working on my app today and have 2 procs that are now at ver 4.

    2. Although a new proc is visible immediately and can be added to an App, it seems the definition is not understood, or for some reason, error 400 occurs. This will eventually go away after an hour or so, and the proc will work – or restarting the GateWay will make it work immediately.

    3. Sometimes, Saving and Publishing do not update the app. Better feedback about what is going on behind the scenes would help to know that a new version of the app is ready.

    4. When adding procs to an app as data sources, there is a search bar to search the database object. The search bar has 2 issues: it ignores schemas and fails if any upper-case characters are typed in (even if they match the results!).

  7. Previous comment was from a few days ago. Today I am up to suffix 8 for my stored procs. I have 5 of them now. 2 doing selects and 3 doing CRUD (updates actually). My renaming/restarting method above has not worked this time (I will try again later).
    The frustrating thing is that the app is down till I can fix this. Fortunately, we are still in a testing phase. If this was in production, I would be embarrassed.
    The other problem is that now I have to have separate crud procs for my desktop (O365) app and my mobile app – I can’t be renaming procs for the desktop so I have to have duplicates in a schema called “mob”. (rant over)

      1. good point, I’ll be careful. I only just got into power apps with this option available. Would hate to rebuild using power flows for the crud. I’m happy to help with any testing or information that I can provide from using this preview feature in the wild. Going live on Monday.

        Following on from the failed update earlier today … after a few hours I tried again, and the app was working – with no changes!!! However, I made a few minor UI changes, and it broke again. So, on to suffix 9. 15mins work reconnecting everything … fails. oh, but try again 10mins later and it works. The failures are on both mobile and power apps desktop. But during the 403 errors the app works perfectly in make.powerapps and the make-play method. Once I have it working it’s stable so long as I don’t fiddle and publish a new version. I will just need to take it carefully.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from SharePains by Microsoft MVP Pieter Veenstra

Subscribe now to keep reading and get access to the full archive.

Continue reading