Thursday, March 15, 2012

Using a Stored Procedure that Returns Multiple Results



Microsoft did a brilliant thing in SQL Server.  I applaud them for this.  You can actually pack more than one SQL Query into a stored procedure and have a single procedure return multiple result sets in one pass.  So I used this feature to write a stored procedure that gathers all the data I need for a certain .rdlc report in my app.  Now I can use this one stored procedure to gather all the data in one fell swoop.





I have done this kind of multiple result set stored procedures in the past and it's a simple matter in code to sort out the data tables, as they are returned in order. Here is some sample code for another instance of this method.





/// <summary>
/// gets the dataset from the database.
/// </summary>
public void Load_Data()
{
    SqlCommand myCommand = new SqlCommand("[dbo].[ExtractWebData]", myConnection);
    myCommand.CommandType = CommandType.StoredProcedure;

    System.Data.SqlClient.SqlDataAdapter adapter = new System.Data.SqlClient.SqlDataAdapter(myCommand);
    ds = new DataSet();
    adapter.Fill(ds);
    ds.Tables[0].TableName = "Customers";
    ds.Tables[1].TableName = "Purchase_Orders";
    ds.Tables[2].TableName = "Purchase_Order_Details";
    ds.Tables[3].TableName = "Inventory";           
}




Now if there was just some way to use that in a report.  It would be great to use a stored procedure to twist all the data into shape before handing it off to a reporting tool!  So you create an xsd. You add a table adapter.



You tell it to use your existing stored procedure.





 You select your stored procedure, and there's the first dataset... But wait.  How do you tell it where the other result sets are?  I want to use all 3 datasets! 







Except that you can't do that.  You see, the .rdlc report requires that you have the data available at design time in order to design the report.  And there is no way to import multiple datasets at once into the .xsd at design time.



From this document: http://msdn.microsoft.com/en-us/library/dd239331.aspx





If multiple result sets are retrieved through a single query, only the
first result set is processed, and all other result sets are ignored.
For example, when you run the following query in the text-based query
designer, only the result set for Production.Product appears in the result pane:






SELECT ProductID FROM Production.Product
GO
SELECT ContactID FROM Person.Contact







I have no idea what the text-based query designer is, but as we saw in SQL Server Management Studio...









In my opinion, this is an EPIC DESIGN FAIL on the part of Microsoft.



We know from the earlier code snippet that Visual Studio can access the data, it just - for some stupid reason - is designed in such a way as to disable this feature in certain cases.  This is completely unacceptable.  But until Microsoft fixes this glaring, stupid, boneheaded omission, we're stuck with it.



Now, I know this blog has no regular readers.  You didn't find this page because you're a fan of Visual Studio Journey.  You found it because you were googling for this problem, and there were no answers anywhere else.  I wish I had better news, but I don't.



Here is the only way I know to work around this issue.  Unravel your stored procedure and execute the whole thing in your client.  Convert each piece into individual queries, and add those to your .xsd.



Alternately, you could split your stored procedure into multiple pieces, like Proc1, Proc2, Proc3... but then you've kind of lost the convenience of the one-stop shopping the stored procedure offers.



Just to be clear: I think that the ability to return multiple result sets from a stored procedure is awesome!  Kudos to the SQL Server development team.  If only the Visual Studio guys would catch some of that brilliance, things would be great.



Addendum:

Just to make myself clear, I think that this feature has awesome potential and multi-table stored procedures are still incredibly useful in Visual Studio.  They just are not usable for rdlc reports (the one thing they would be most ideally suited for in an ideal world).



...




Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Tuesday, March 6, 2012

How to easily compare 2 SQL Server Databases.

NOTE: this is for SQL SERVER databases only.  It will not sync Oracle to Interbase or MySql to Sybase.  However, application of this technique may apply to any two databases of the same type. (i.e. oracle to oracle)



I had lost access to the  production database for a time, and wanted to ensure that I had propagated all my recent changes from Development to production - without spending $895 for a SQL management and database analysis system.



So here's how I proceeded to sync my tables from one database to the other.



Open the Production database (or a current backup of it) in SQL Server Management studio.

use this query:


SELECT

    TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, DATETIME_PRECISION

FROM INFORMATION_SCHEMA.COLUMNS

where TABLE_SCHEMA='dbo'

order by 1,2,4

Note: these columns were important to me, feel free to modify the columns as you see fit.  Also I only cared about the 'dbo' schema, so I filtered for that.  Your needs may vary.



This will give you the column info for all tables in the 'dbo' schema.



Now, save the data by right clicking the grid and selecting Save Results As.



Give it a name like Production_Schema and save as .txt.



Note: csv works too, but I find txt easier to compare.



Next do the same with the development database, naming it something like Development_Schema.txt.



Now you need a diff tool like WinMerge.  Compare these 2 files to see where they differ.  The text files cover all columns in all datatables and views in the schema.





Now go through the differences and see what changes have to be made in production so your software doesn't crash.  When I did this, I noted that there were some changes that were not ready for prime-time yet, so I left them unfixed in production.



The only thing left to compare once this is complete are the stored procedures and functions.  I just made a fresh, empty query and did a Script Stored Procedure As > Drop and Create to > Clipboard and pasted every one of them into the query. I saved it as AllFunctions.SQL and ran it in production to sync the functions.







 I hope this helps!



Comments are welcome!

...




Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Tuesday, December 20, 2011

Incrementing a Non Numeric Index in SQL Server

So I have this client, and all his sales invoices in the old system are either numeric, or they are numeric (1000) with a single character prefix (C1000).   We want to auto increment the index automatically, but the autoincrement stuff is not going to work here.



So I wrote a function based on this SQL.




select 'C' + isnull(cast(1+max( cast(SUBSTRING(Invoice_no,2,99) as int)) as varchar),'1000')
from Sales where Invoice_No like 'C%'

Let's work from the inside out.


  1. Invoice_no is the column to increment.  ('C1234')

  2. first we substring the first character off with SUBSTRING(Invoice_no,2,99) ('1234')

  3. we use cast to find the integer of it (1234)

  4. we use 1+max to aggregate (find the max value of this integer) and add one. (1235)

  5. we cast the result back to a varchar ('1235')

  6. then - if isnull gives us a nulll, we use the hard-coded value of '1000'

  7. we prepend the 'C' back on  ('C1235')




Now we make this into a function so we can use it like "GetDate()" in the default value of the column.




ALTER FUNCTION [dbo].[NextSalesID] ()

RETURNS varchar(10)
AS
BEGIN
    DECLARE @Answer varchar(10)   
    select @Answer= 'C' + isnull(cast(1+max( cast(SUBSTRING(Invoice_no,2,99) as int)) as varchar),'1000')
    from Sales where Invoice_No like 'C%'
    RETURN @Answer
END

 Now we have to add it as the default value for our column.  This is accomplished by editing the table in SQL Server Management Studio, selecting the column, and...




Binding a scalar Function to a Column Default

MAKE SURE that management studio doesn't add quotes '' around your function name.











Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Saturday, November 19, 2011

Using Return Values From Stored Procedures in C#.NET

Ok, let's say you have a stored procedure that returns a value.






Now lets say you want to test it in SQL Server Management Studio...






This gives us a value of 1, as expected.



Now if we want to call this from C#, there is a little trick we have to play with Parameters.






Note the trick we had to play here (line 19) to access the return value after the procedure runs.  At first, I tried using:

i=myCommand.ExecuteNonQuery();

...but that always yielded a value of -1.







Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Friday, June 17, 2011

Massive ReportViewer Headache Relieved

Ok I like organization.  Too much perhaps.  But when my project root folder gets full (Microsoft likes everything in there)  I get tired of fishing around for all the parts of everything.  Did I name that thing reportInventory, ir InventoryReport?  So I like to make folders for everything, like so.












Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Tuesday, March 29, 2011

Using SQL Server Authentication on SQL Express

For most of my databases, I am content to use Windows Authentication for my database access.  In a development or small shop environment, it's usually acceptable to let Windows bear the burden of authentication.

But if you need to add just one database app that requires a separate login beyond the Windows login, here's how.



First a few definitions.

SERVER vs. DATABASE

SQL Server (in my case express 2008 R2)  is not a Database.  In the management studio, when you log into the management studio, you can see that .\SQLEXPRESS (the root node) is called a server.  It is important to read this article carefully when I talk about servers vs. databases, as it makes a difference.



LOGIN vs. USER

This is a little more blurry, but a login is not much more than a name, password, and a set of permissions to access the server.  A user exists in databases, and has specific roles and permissions in an individual database.



Getting Started

In the Mode

First, make sure your server is in the mode (mood?) to use both kinds of authentication.

Open SQL Server Management Studio and right-click the SERVER name.  Pick properties.

Then on the Security tab, make sure SQL Server and Windows Authentication mode is selected.

If it wasn't, then you'll need to save the change and restart SQL Server.  If it was already selected you can skip this section.

Restarting SQL Server

Return to the SQL Server Management Studio and right click the Server Name.

Select restart.



Create a Server Login

When we create logins, in general we want to create one login per user. First, log into management studio using windows authentication (or however you normally gain admin access).  Under the server tree (not a database tree) select Security- Logins and pick New Login.







Add your login... 

Make sure to add a password and select the default database.

 

On the User Mapping tab...

Select the checkbox by your database.

Enter dbo as the default schema

Check every permission that doesn't contain the word deny.

Note that there are some additional roles in my database that I had added previously.

 On the Status tab, make sure grant and enabled are selected.

Click OK.

Using witch-hazel and fairy dust, Management studio will now create your LOGIN to the SERVER, and your USER in the DATABASE.



Look in the Databases tree and find the user created by the wizard.

Open his properties.



The General tab should look much like this.



Testing

To test your new user/login, open a second copy of SQL Server Management Studio.

Change to SQL Server Authentication and enter your user login info.

If you forgot the password (as I did about 6 times while writing this article) you can go back to the login tree in your first SQL Server Management Studio window and change it there, then try again.



Now it's easy to use this login in your programs to access this database.  It's also easy to set database level permissions, roles etc.



in C# to create a connection string to access the database do this:










Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, March 3, 2011

SQL Server 2008 R2 Express

Three Hours later...

What a bunch of USELESS CRAP!



For those who lack a life, the text in the box below is...



The following notes apply to this release of SQL Server only.



Microsoft Update



For information about how to use Microsoft Update to identify updates for SQL Server 2008 R2, see the Microsoft Update Web site at http://go.microsoft.com/fwlink/?LinkId=108409.



Samples



By default, sample databases and sample code are not installed as part of SQL Server Setup. To install sample databases and sample code for non-Express editions of SQL Server 2008 R2, see the CodePlex Web site at http://go.microsoft.com/fwlink/?LinkId=87843. To read about support for SQL Server sample databases and sample code for SQL Server Express, see Databases and Samples Overview on the CodePlex Web site at http://go.microsoft.com/fwlink/?LinkId=110391.



Release Notes



For more information about late-breaking changes in this release of SQL Server, see the latest readme file at http://go.microsoft.com/fwlink/?LinkId=141691.



Documentation and Links



To install the .NET Framework SDK, see “Installing the .NET Framework SDK” in SQL Server 2008 R2 Books Online at http://go.microsoft.com/fwlink/?LinkId=141693.



For information about SQL Server 2008 R2 Surface Area Configuration, see the following SQL Server 2008 R2 documentation topics:



In SQL Server 2008 R2 Books Online: “Understanding Surface Area Configuration.”



In SQL Server 2008 R2 Setup Help: “Minimize SQL Server 2008 R2 Surface Area.”



In SQL Server 2008 R2 Books Online on MSDN: Understanding Surface Area Configuration at http://go.microsoft.com/fwlink/?LinkId=141692.
And the log file it left says



Overall summary:

  Final result:                  Failed: see details below

  Exit code (Decimal):           -2068052398

  Exit facility code:            1212

  Exit error code:               1618

  Exit message:                  Failed: see details below

  Start time:                    2011-03-03 15:55:52

  End time:                      2011-03-03 16:52:14

  Requested action:              Upgrade

  Log with failure:              C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\20110303_155335\sql_engine_core_inst_ctp6_Cpu32_1.log

  Exception help link:           http://go.microsoft.com/fwlink?LinkId=20476&ProdName=Microsoft+SQL+Server&EvtSrc=setup.rll&EvtID=50000&ProdVer=10.50.1600.1



Machine Properties:

  Machine name:                  WEB1

  Machine processor count:       2

  OS version:                    Windows Server 2003

  OS service pack:               Service Pack 2

  OS region:                     United States

  OS language:                   English (United States)

  OS architecture:               x86

  Process architecture:          32 Bit

  OS clustered:                  No



Product features discovered:

  Product              Instance             Instance ID                    Feature                                  Language             Edition              Version         Clustered

  Sql Server 2008      SQLEXPRESS           MSSQL10.SQLEXPRESS             Database Engine Services                 1033                 Express Edition      10.1.2531.0     No       

  Sql Server 2008      SQLEXPRESS           MSSQL10.SQLEXPRESS             SQL Server Replication                   1033                 Express Edition      10.1.2531.0     No       

  Sql Server 2008                                                          Management Tools - Basic                 1033                 Express Edition      10.0.1600.22    No       



Package properties:

  Description:                   SQL Server Database Services 2008 R2

  ProductName:                   SQL Server 2008 R2

  Type:                          RTM

  Version:                       10

  SPLevel:                       0

  Installation location:         d:\bf7ec28684b1818f6c3151c67288a7c8\x86\setup\

  Installation edition:          EXPRESS_ADVANCED



User Input Settings:

  ACTION:                        Upgrade

  AGTDOMAINGROUP:                <empty>

  BROWSERSVCSTARTUPTYPE:         Automatic

  CONFIGURATIONFILE:            

  CUSOURCE:                     

  ENU:                           True

  ERRORREPORTING:                False

  FAILOVERCLUSTERROLLOWNERSHIP:  2

  FARMACCOUNT:                   <empty>

  FARMADMINPORT:                 0

  FARMPASSWORD:                  *****

  FTSVCACCOUNT:                  <empty>

  FTSVCPASSWORD:                 *****

  FTUPGRADEOPTION:               Import

  HELP:                          False

  IACCEPTSQLSERVERLICENSETERMS:  False

  INDICATEPROGRESS:              False

  INSTANCEID:                    SQLEXPRESS

  INSTANCENAME:                  SQLEXPRESS

  ISSVCACCOUNT:                  NT AUTHORITY\NetworkService

  ISSVCPASSWORD:                 *****

  ISSVCSTARTUPTYPE:              Automatic

  PASSPHRASE:                    *****

  PCUSOURCE:                    

  PID:                           *****

  QUIET:                         False

  QUIETSIMPLE:                   False

  RSCATALOGSERVERINSTANCENAME:   Unknown

  RSUPGRADEDATABASEACCOUNT:     

  RSUPGRADEPASSWORD:             *****

  SQLDOMAINGROUP:                <empty>

  SQMREPORTING:                  True

  UIMODE:                        AutoAdvance

  X86:                           False



  Configuration file:            C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\20110303_155335\ConfigurationFile.ini



Detailed results:

  Feature:                       Database Engine Services

  Status:                        Passed

  MSI status:                    Passed

  Configuration status:          Passed



  Feature:                       SQL Client Connectivity

  Status:                        Passed

  MSI status:                    Passed

  Configuration status:          Passed



  Feature:                       SQL Client Connectivity SDK

  Status:                        Passed

  MSI status:                    Passed

  Configuration status:          Passed



  Feature:                       SQL Writer

  Status:                        Passed

  MSI status:                    Passed

  Configuration status:          Passed



  Feature:                       SQL Browser

  Status:                        Passed

  MSI status:                    Passed

  Configuration status:          Passed



  Feature:                       SQL Server Replication

  Status:                        Passed

  MSI status:                    Passed

  Configuration status:          Passed



  Feature:                       SQL Compact Edition Runtime

  Status:                        Passed

  MSI status:                    Passed

  Configuration status:          Passed



  Feature:                       Management Tools - Basic

  Status:                        Passed

  MSI status:                    Passed

  Configuration status:          Passed



Rules with failures:



Global rules:



Scenario specific rules:



Rules report file:               C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\20110303_155335\SystemConfigurationCheck_Report.htm









Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

How to Auto-generate Order Line Item numbers for bulk uploads

 I had a problem where I had 17000 line items to insert into 9000 orders. The system required line item numbers, preferably numbered 1throug...