{
    "metadata": {
        "kernelspec": {
            "name": "SQL",
            "display_name": "SQL",
            "language": "sql"
        },
        "language_info": {
            "name": "sql",
            "version": ""
        }
    },
    "nbformat_minor": 2,
    "nbformat": 4,
    "cells": [
        {
            "cell_type": "markdown",
            "source": "<img src=\"https://github.com/Microsoft/azuredatastudio/blob/master/samples/notebookSamples/Graphics/AzureDataStudioLogo.png?raw=true\" width=\"10%\">\r\n\r\n## SQL Notebooks in Azure Data Studio\r\n\r\nNotebooks allow rich text, images, code, and resultsets to be easily shared. This is a concept that is widely used in data science and which we feel is well suited to SQL work. \r\n",
            "metadata": {}
        },
        {
            "cell_type": "code",
            "source": "select \r\n    'Hello SQL World' as [Greetings], \r\n    @@servername as [Server Name],\r\n    datename(weekday,getutcdate()) as [Today]",
            "metadata": {},
            "outputs": [],
            "execution_count": 1
        },
        {
            "cell_type": "markdown",
            "source": "### Concepts\r\n\r\nNotebooks are saved in a file format of .ipynb and have a couple of logical components.\r\n\r\n**Kernel**\r\n\r\nThe language and execution environment of the notebook. Common examples are Python, R, Scala, and Spark. Azure Data Studio also offers a SQL kernel, which is the focus of this tutorial.\r\n\r\n**Attach To**\r\n\r\nThis is the compute environment for the code - basically, where it will run. For SQL this is exactly analogous to the familiar Connection property of a query.\r\n\r\n**Cell**\r\n\r\nA cell is an editable section of the notebook. Cells can be human-readable text or code. Text cells are edited in the Markdown language to allow formatting and can include rich content including images. In Azure Data Studio, code cells include intellisense where possible. Below is an example of a SQL code cell.\r\n",
            "metadata": {}
        },
        {
            "cell_type": "code",
            "source": "select top 5 * from sys.dm_exec_session_wait_stats order by wait_time_ms desc",
            "metadata": {},
            "outputs": [
                {
                    "output_type": "display_data",
                    "data": {
                        "text/html": "(5 rows affected)"
                    },
                    "metadata": {}
                },
                {
                    "output_type": "display_data",
                    "data": {
                        "text/html": "Total execution time: 00:00:00.163"
                    },
                    "metadata": {}
                },
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "execution_count": 7,
                    "data": {
                        "application/vnd.dataresource+json": {
                            "schema": {
                                "fields": [
                                    {
                                        "name": "session_id"
                                    },
                                    {
                                        "name": "wait_type"
                                    },
                                    {
                                        "name": "waiting_tasks_count"
                                    },
                                    {
                                        "name": "wait_time_ms"
                                    },
                                    {
                                        "name": "max_wait_time_ms"
                                    },
                                    {
                                        "name": "signal_wait_time_ms"
                                    }
                                ]
                            },
                            "data": [
                                {
                                    "0": "59",
                                    "1": "ASYNC_NETWORK_IO",
                                    "2": "24",
                                    "3": "389",
                                    "4": "347",
                                    "5": "0"
                                },
                                {
                                    "0": "57",
                                    "1": "PREEMPTIVE_XE_GETTARGETSTATE",
                                    "2": "9",
                                    "3": "160",
                                    "4": "102",
                                    "5": "0"
                                },
                                {
                                    "0": "57",
                                    "1": "ASYNC_NETWORK_IO",
                                    "2": "323",
                                    "3": "38",
                                    "4": "2",
                                    "5": "10"
                                },
                                {
                                    "0": "58",
                                    "1": "MEMORY_ALLOCATION_EXT",
                                    "2": "5066",
                                    "3": "25",
                                    "4": "0",
                                    "5": "0"
                                },
                                {
                                    "0": "60",
                                    "1": "PAGEIOLATCH_SH",
                                    "2": "30",
                                    "3": "11",
                                    "4": "0",
                                    "5": "0"
                                }
                            ]
                        },
                        "text/html": "<table><tr><th>session_id</th><th>wait_type</th><th>waiting_tasks_count</th><th>wait_time_ms</th><th>max_wait_time_ms</th><th>signal_wait_time_ms</th></tr><tr><td>59</td><td>ASYNC_NETWORK_IO</td><td>24</td><td>389</td><td>347</td><td>0</td></tr><tr><td>57</td><td>PREEMPTIVE_XE_GETTARGETSTATE</td><td>9</td><td>160</td><td>102</td><td>0</td></tr><tr><td>57</td><td>ASYNC_NETWORK_IO</td><td>323</td><td>38</td><td>2</td><td>10</td></tr><tr><td>58</td><td>MEMORY_ALLOCATION_EXT</td><td>5066</td><td>25</td><td>0</td><td>0</td></tr><tr><td>60</td><td>PAGEIOLATCH_SH</td><td>30</td><td>11</td><td>0</td><td>0</td></tr></table>"
                    }
                }
            ],
            "execution_count": 7
        },
        {
            "cell_type": "markdown",
            "source": "**Results**\r\n\r\nCode cells can be executed against the environment specified in Attach To, and their results are saved into the notebook. Once executed and saved, the results can be opened with the file without having be be re-executed. Results may be text, grids, charts, or other visualizations.\r\n\r\n**Trusted vs Non-Trusted**\r\n\r\nSince notebooks can contain HTML and Javascript code, it would be possible for a maliciously formed notebook to execute code simply upon being opened by the user. To prevent this, notebooks have the concept of \"Trusted\" and \"Untrusted.\" Untrusted HTML is sanitized and untrusted Javascript is not executed. Users can mark notebooks trusted if necessary, but in common use cases an untrusted notebook will perform the same as a trusted one. This is similar to the behavior of many other file types when downloaded from the internet.",
            "metadata": {}
        },
        {
            "cell_type": "markdown",
            "source": "### Editing Experience\r\n\r\nEditing SQL is the same in Azure Data Studio notebooks as in the Azure Data Studio query editor - the same Intellisense, the same snippet support. Markdown is edited with a custom editor which shows a preview during edit, and only shows the processed markdown when not in edit mode. Code and markdown (text) cells can be added with buttons or through context menus.",
            "metadata": {}
        },
        {
            "cell_type": "code",
            "source": "select top 10 * from sys.databases",
            "metadata": {},
            "outputs": [],
            "execution_count": 1
        },
        {
            "cell_type": "markdown",
            "source": "### Code Separation and Context\r\n\r\nThe separate code cells in a SQL notebook are run as separate batches. This is equivalent to having a GO statement between cells.\r\n\r\nThis is an area we're actively innovating in and want to make a little more straightforward! But we'll describe the current behavior.\r\n\r\nIn this code, we're setting the database context to WideWorldImporters and then creating a local variable. We're also setting nocount on, to demonstrate set statement behavior.",
            "metadata": {}
        },
        {
            "cell_type": "code",
            "source": "set nocount on;\r\nuse WideWorldImporters;\r\ndeclare @i int;\r\nset @i = 1;\r\nselect @i [Value of @i], db_name() as [MyDatabaseName]",
            "metadata": {},
            "outputs": [],
            "execution_count": 1
        },
        {
            "cell_type": "markdown",
            "source": "The next cell will show an error, since the variable @i is not declared within this cell.",
            "metadata": {}
        },
        {
            "cell_type": "code",
            "source": "select @i [Value of @i], db_name() as [MyDatabaseName]",
            "metadata": {},
            "outputs": [],
            "execution_count": 1
        },
        {
            "cell_type": "markdown",
            "source": "In the next cell, we're re-declaring @i, but not setting it, so the value remains null.\r\n\r\nHowever, the previously set database context and nocount settings are maintained as these are durable throughout the session. This is the same behavior as the query editor.",
            "metadata": {}
        },
        {
            "cell_type": "code",
            "source": "declare @i int;\r\nselect @i [Value of @i], db_name() as [MyDatabaseName]",
            "metadata": {},
            "outputs": [],
            "execution_count": 1
        },
        {
            "cell_type": "markdown",
            "source": "One upshot of this - not unique to SQL notebooks - is that code cell execution order *does matter*\r\n\r\nWe think this is an area we can innovate in and welcome your suggestions on how to make this easier to work with in a notebook context.",
            "metadata": {}
        },
        {
            "cell_type": "markdown",
            "source": "### Multi-language support\r\n\r\nWhile in a SQL notebook you can change to run R and Python on the SQL Server with a special syntax. This allows you to type your raw Python or R and execute it without having to remember how to wrap it up in a stored procedure (provided that the Advanced Analytics Extensions feature is installed and enabled on the target server)",
            "metadata": {}
        },
        {
            "cell_type": "code",
            "source": "%%lang_python\r\nprint (\"Hello World\")",
            "metadata": {
                "language": "python"
            },
            "outputs": [
                {
                    "output_type": "display_data",
                    "data": {
                        "text/html": "STDOUT message(s) from external script: \nHello World\r"
                    },
                    "metadata": {}
                },
                {
                    "output_type": "display_data",
                    "data": {
                        "text/html": "Total execution time: 00:00:21.211"
                    },
                    "metadata": {}
                }
            ],
            "execution_count": 1
        },
        {
            "cell_type": "markdown",
            "source": "### Use Cases\r\n\r\nWe're envisioning a number of use cases for the SQL notebooks. In many ways it's simply the next generation experience for the query editor, and many of the things you can do in a plain editor can be done as well or better in a notebook. But a few scenarios have jumped out at us:\r\n\r\n- Teaching Tools \r\n- Runbooks\r\n- Business reporting and presentations\r\n- Troubleshooting\r\n- Deployments\r\n- Baselining\r\n\r\nWe're excited to learn what the community can do with them!",
            "metadata": {}
        },
        {
            "cell_type": "markdown",
            "source": "**Example Server Information Report**\r\n\r\nRun this report and save it to a known location to maintain a basic point in time inventory.",
            "metadata": {}
        },
        {
            "cell_type": "code",
            "source": "--Server basics\r\nSELECT\r\n    getutcdate() as DateRun, \r\n    db_name() as DatabaseName,\r\n    serverproperty('ServerName') as ServerName,\r\n    serverproperty('InstanceName') as InstanceName,\r\n    serverproperty('ComputerNamePhysicalNetBIOS') as PhysicalName,\r\n    serverproperty('Edition') as Edition,\r\n    serverproperty('ProductMajorVersion') as MajorVersion,\r\n    serverproperty('ProductMinorVersion') as MinorVersion\r\n\r\n--Databases\r\nSELECT *\r\nfrom sys.databases",
            "metadata": {},
            "outputs": [],
            "execution_count": 1
        },
        {
            "cell_type": "markdown",
            "source": "**More SQL Examples**\r\n\r\n",
            "metadata": {}
        },
        {
            "cell_type": "code",
            "source": "DECLARE @i INT,  @c varchar(26);\r\nSELECT @i = 65, @c = '';\r\nWHILE (@i < 93)\r\nBEGIN\r\n    SELECT @c = concat(@c,CHAR(@i))\r\n    SET @i = @i + 1\r\nEND\r\n\r\n\r\nSELECT @c as \"Letters\", len(@c) as \"Count\"",
            "metadata": {},
            "outputs": [],
            "execution_count": 1
        },
        {
            "cell_type": "code",
            "source": "DROP TABLE IF EXISTS [dbo].[MyNotebookTable]\r\nCREATE TABLE [dbo].[MyNotebookTable]\r\n(\r\n    [Id] INT IDENTITY NOT NULL PRIMARY KEY, -- Primary Key column\r\n    [FirstValue] NVARCHAR(50) NOT NULL,\r\n    [SecondValue] NVARCHAR(50) NOT NULL\r\n);\r\n\r\nPRINT 'Success: Created MyNotebookTable'\r\n",
            "metadata": {},
            "outputs": [],
            "execution_count": 1
        },
        {
            "cell_type": "code",
            "source": "raiserror('Something bad happened!',0,1) with nowait;\r\nwaitfor delay '00:00:05'\r\nraiserror('Something bad happened... again!',0,1) with nowait;",
            "metadata": {},
            "outputs": [],
            "execution_count": 1
        }
    ]
}
