Stored procedure returns int instead of result set

后端 未结 17 2021
说谎
说谎 2020-12-03 13:02

I have a stored procedure that contains dynamic select. Something like this:

ALTER PROCEDURE [dbo].[usp_GetTestRecords] 
    --@p1 int = 0, 
    --@p2 int =          


        
17条回答
  •  眼角桃花
    2020-12-03 13:53

    See Ladislav Mrnka's answer in this Stack Overflow post https://stackoverflow.com/a/7131344/4318324

    I had the same basic problem.

    Adding

    SET FMTONLY OFF
    

    To a procedure you are trying to import during the import will address this problem. It's a good practice to remove the line afterwards unless the purpose of the database is solely to provide schema for EF (Entity Framework).

    The main reason for caution is that EF uses this setting to prevent data mutations when trying to obtain metadata.

    If you refresh your entity model from a database any procedures with this line in them can potentially update the data in that database just by trying to obtain the schema.

    I wanted to add a further note on this so it's not needed to fully scan through the other link.

    if you want to try to use FMTONLY here are a couple things to keep in mind.

    when FMTONLY is on:
      1) only the schema is returned (no) rows.
         similar to adding a blanket false statement to your where clause (ie "where 1=0")
      2) flow control statements are ignored
    

    Example

    set fmtonly on
    
    if 1=1
    begin
        select 1 a
    end
    else
    begin
        select 1 a,2 b
    end
    
    while 1=1
    select 1 c
    

    The above returns NO rows whatsoever and the metadata for each of the three queries

    For this reason some people suggest toggling it off in a way that takes advantage of it's non-observance of flow control

    if 1=0
    begin
        set fmtonly off
    end
    

    In fact you could use this to introduce logic that tracks this

    set fmtonly off
    declare @g varchar(30)
    set @g = 'fmtonly was set to off'
    
    if 1=0
    begin
        set fmtonly off
        set @g = 'fmtonly was set to on' 
    end
    
    select @g
    

    Think VERY CAREFULLY before trying to use this feature as it is both deprecated and potentially makes sql extremely hard to follow

    the MAIN concepts that need to be understood are the following

    1. EF turns FMTONLY on to prevent MUTATING data from executing stored procedures
       when it executes them during a model update.
       (from which it follows)
    
    2. setting FMTONLY off in any procedure that EF will attempt to do a schema scan
       (potentially ANY and EACHONE) introduces the potential to mutate database
       data whenever *anyone* attempts to update their database model.
    

提交回复
热议问题