Microsoft SQL Server
Microsoft SQL Server Integration
Section titled “Microsoft SQL Server Integration”Connect Querri to your Microsoft SQL Server database to run queries, analyze data, and create visualizations.
Overview
Section titled “Overview”The SQL Server connector supports:
- SQL Server 2016+: All modern SQL Server versions
- SQL Server 2019: Full support including new features
- SQL Server 2022: Latest version support
- Azure SQL Database: Managed SQL Server on Azure
- Azure SQL Managed Instance: Enterprise features on Azure
- Amazon RDS for SQL Server: Managed SQL Server on AWS
Prerequisites
Section titled “Prerequisites”- SQL Server database instance
- Database credentials with appropriate permissions
- Network access to the database
IP Whitelisting
Section titled “IP Whitelisting”Important: For cloud-hosted databases or databases behind firewalls, whitelist the following IP address:
18.189.33.77This is Querri’s outbound IP address. Add this to your database firewall rules or security group.
Creating the Connector
Section titled “Creating the Connector”-
Navigate to Connectors
- Go to Settings → Connectors
- Click “Add Connector”
-
Select Microsoft SQL Server
- Choose “Microsoft SQL Server” from the database connectors
-
Configure Connection
Host: your-server.database.windows.netPort: 1433 (default SQL Server port)Database: your_database_nameUsername: your_usernamePassword: your_passwordOptional Settings:
- Authentication: SQL Server Authentication or Windows Authentication
- Encrypt: Enable for encrypted connections (recommended)
- Trust Server Certificate: For self-signed certificates
- Application Name: Identify Querri connections
-
Test Connection
- Click “Test Connection” to verify
- If successful, click “Save”
-
Use in Projects
- Create a new step → “Database Query”
- Select your SQL Server connector
- Write your T-SQL query
Network Configuration
Section titled “Network Configuration”Azure SQL Database
Section titled “Azure SQL Database”Add firewall rule:
Rule Name: QuerriStart IP: 18.189.33.77End IP: 18.189.33.77Via Azure Portal:
- Go to your SQL Database
- Click “Set server firewall”
- Add the IP address
- Click “Save”
AWS RDS SQL Server
Section titled “AWS RDS SQL Server”Add inbound rule to security group:
Type: MS SQLProtocol: TCPPort: 1433Source: 18.189.33.77/32Description: Querri AccessOn-Premises SQL Server
Section titled “On-Premises SQL Server”Configure Windows Firewall:
New-NetFirewallRule -DisplayName "SQL Server" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 1433 ` -RemoteAddress 18.189.33.77 ` -Action AllowEnable TCP/IP in SQL Server Configuration Manager:
- Open SQL Server Configuration Manager
- SQL Server Network Configuration → Protocols
- Enable TCP/IP
- Restart SQL Server service
Database User Setup
Section titled “Database User Setup”Read-Only User (Recommended)
Section titled “Read-Only User (Recommended)”Create a dedicated read-only user for Querri:
-- Create loginCREATE LOGIN querri_readonlyWITH PASSWORD = 'SecurePassword123!';
-- Switch to your databaseUSE your_database;
-- Create userCREATE USER querri_readonlyFOR LOGIN querri_readonly;
-- Grant read permissionsALTER ROLE db_datareader ADD MEMBER querri_readonly;
-- Allow view of database metadataGRANT VIEW DEFINITION TO querri_readonly;Read-Write User (If Needed)
Section titled “Read-Write User (If Needed)”-- Create loginCREATE LOGIN querri_readwriteWITH PASSWORD = 'SecurePassword123!';
-- Switch to your databaseUSE your_database;
-- Create userCREATE USER querri_readwriteFOR LOGIN querri_readwrite;
-- Grant read-write permissionsALTER ROLE db_datareader ADD MEMBER querri_readwrite;ALTER ROLE db_datawriter ADD MEMBER querri_readwrite;
-- Grant execute permissions (for stored procedures)GRANT EXECUTE TO querri_readwrite;Verify Permissions
Section titled “Verify Permissions”-- Check loginSELECT * FROM sys.server_principalsWHERE name = 'querri_readonly';
-- Check user permissionsSELECT dp.name as username, dp.type_desc, o.name as object_name, p.permission_name, p.state_descFROM sys.database_permissions pJOIN sys.database_principals dp ON p.grantee_principal_id = dp.principal_idLEFT JOIN sys.objects o ON p.major_id = o.object_idWHERE dp.name = 'querri_readonly';Example Queries
Section titled “Example Queries”Basic SELECT
Section titled “Basic SELECT”SELECT customer_id, customer_name, email, created_atFROM customersWHERE status = 'active'ORDER BY created_at DESCOFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;Aggregate Query with CTE
Section titled “Aggregate Query with CTE”WITH monthly_sales AS ( SELECT FORMAT(order_date, 'yyyy-MM') as month, COUNT(*) as order_count, SUM(total_amount) as total_revenue, AVG(total_amount) as avg_order_value FROM orders WHERE order_date >= DATEADD(MONTH, -12, GETDATE()) GROUP BY FORMAT(order_date, 'yyyy-MM'))SELECT *FROM monthly_salesORDER BY month DESC;JOIN with Window Functions
Section titled “JOIN with Window Functions”SELECT c.customer_name, c.email, COUNT(o.order_id) as order_count, SUM(o.total_amount) as lifetime_value, RANK() OVER (ORDER BY SUM(o.total_amount) DESC) as customer_rankFROM customers cLEFT JOIN orders o ON c.customer_id = o.customer_idWHERE c.status = 'active'GROUP BY c.customer_id, c.customer_name, c.emailHAVING COUNT(o.order_id) > 0ORDER BY lifetime_value DESCOFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY;Dynamic Date Ranges
Section titled “Dynamic Date Ranges”SELECT product_name, category, SUM(quantity) as units_sold, SUM(total_amount) as revenueFROM salesWHERE sale_date >= CAST('{{start_date}}' AS DATE) AND sale_date < CAST('{{end_date}}' AS DATE)GROUP BY product_name, categoryORDER BY revenue DESC;Performance Optimization
Section titled “Performance Optimization”Use Indexes
Section titled “Use Indexes”Create indexes on frequently queried columns:
CREATE NONCLUSTERED INDEX IX_orders_customerON orders(customer_id)INCLUDE (order_date, total_amount);
CREATE NONCLUSTERED INDEX IX_orders_dateON orders(order_date)INCLUDE (customer_id, total_amount);Check Index Usage
Section titled “Check Index Usage”-- View index usage statisticsSELECT OBJECT_NAME(s.object_id) as table_name, i.name as index_name, s.user_seeks, s.user_scans, s.user_lookups, s.user_updatesFROM sys.dm_db_index_usage_stats sJOIN sys.indexes i ON s.object_id = i.object_id AND s.index_id = i.index_idWHERE OBJECT_NAME(s.object_id) = 'orders';Query Execution Plan
Section titled “Query Execution Plan”SET STATISTICS IO ON;SET STATISTICS TIME ON;
-- Your query hereSELECT * FROM orders WHERE customer_id = 123;
-- View execution planSET SHOWPLAN_TEXT ON;Use NOLOCK for Read-Only Queries
Section titled “Use NOLOCK for Read-Only Queries”SELECT *FROM orders WITH (NOLOCK)WHERE order_date >= '2024-01-01';Note: Use NOLOCK carefully, as it can read uncommitted data.
Common Use Cases
Section titled “Common Use Cases”Sales Dashboard
Section titled “Sales Dashboard”SELECT CAST(order_date AS DATE) as date, COUNT(*) as order_count, SUM(total_amount) as revenue, AVG(total_amount) as avg_order_value, COUNT(DISTINCT customer_id) as unique_customersFROM ordersWHERE order_date >= DATEADD(DAY, -30, GETDATE())GROUP BY CAST(order_date AS DATE)ORDER BY date DESC;Customer Lifetime Value
Section titled “Customer Lifetime Value”WITH customer_metrics AS ( SELECT c.customer_id, c.customer_name, c.email, MIN(o.order_date) as first_order_date, MAX(o.order_date) as last_order_date, COUNT(o.order_id) as total_orders, SUM(o.total_amount) as lifetime_value, AVG(o.total_amount) as avg_order_value FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id WHERE c.status = 'active' GROUP BY c.customer_id, c.customer_name, c.email)SELECT *, DATEDIFF(DAY, first_order_date, last_order_date) as customer_age_days, CASE WHEN total_orders >= 10 THEN 'VIP' WHEN total_orders >= 5 THEN 'Regular' WHEN total_orders >= 2 THEN 'Repeat' ELSE 'New' END as segmentFROM customer_metricsWHERE total_orders > 0ORDER BY lifetime_value DESC;Inventory Analysis
Section titled “Inventory Analysis”SELECT p.product_name, p.category, i.current_stock, i.reorder_level, s.supplier_name, COALESCE(recent_sales.units_sold_30d, 0) as units_sold_30d, CASE WHEN i.current_stock = 0 THEN 'OUT OF STOCK' WHEN i.current_stock <= i.reorder_level THEN 'REORDER NOW' WHEN i.current_stock <= i.reorder_level * 1.5 THEN 'LOW STOCK' ELSE 'OK' END as statusFROM products pJOIN inventory i ON p.product_id = i.product_idLEFT JOIN suppliers s ON p.supplier_id = s.supplier_idLEFT JOIN ( SELECT product_id, SUM(quantity) as units_sold_30d FROM sales WHERE sale_date >= DATEADD(DAY, -30, GETDATE()) GROUP BY product_id) recent_sales ON p.product_id = recent_sales.product_idWHERE i.current_stock <= i.reorder_level * 2ORDER BY i.current_stock ASC;Troubleshooting
Section titled “Troubleshooting”Cannot Connect to Server
Section titled “Cannot Connect to Server”Problem: A network-related or instance-specific error
Solutions:
- Verify IP
18.189.33.77is whitelisted - Check SQL Server is running
- Verify TCP/IP is enabled
- Check SQL Server Browser service is running (for named instances)
- Verify firewall allows port 1433
Login Failed
Section titled “Login Failed”Problem: Login failed for user
Solutions:
- Check username and password
- Verify SQL Server authentication is enabled
- Check user exists:
SELECT * FROM sys.server_principals; - Verify database name is correct
- For Azure SQL, ensure format:
username@servername
Cannot Open Database
Section titled “Cannot Open Database”Problem: Cannot open database requested by login
Solutions:
- Verify database name
- Check user has access to database
- Ensure database is online
- Grant permissions to database
SSL/TLS Errors
Section titled “SSL/TLS Errors”Problem: Certificate validation failed
Solutions:
- Enable “Trust Server Certificate” option
- Install proper SSL certificate on server
- Update connection string:
Encrypt=true;TrustServerCertificate=true;
Security Best Practices
Section titled “Security Best Practices”Enable Encryption
Section titled “Enable Encryption”Encrypt: YesTrust Server Certificate: No (use valid certificate)Use Row-Level Security
Section titled “Use Row-Level Security”-- Create security policyCREATE FUNCTION dbo.fn_securitypredicate(@customer_id AS INT)RETURNS TABLEWITH SCHEMABINDINGASRETURN SELECT 1 AS resultWHERE @customer_id = CAST(SESSION_CONTEXT(N'customer_id') AS INT);
CREATE SECURITY POLICY CustomerFilterADD FILTER PREDICATE dbo.fn_securitypredicate(customer_id)ON dbo.ordersWITH (STATE = ON);Audit User Activity
Section titled “Audit User Activity”-- Enable database auditingCREATE DATABASE AUDIT SPECIFICATION querri_auditFOR SERVER AUDIT [Audit-Querri]ADD (SELECT ON DATABASE::your_database BY querri_readonly)WITH (STATE = ON);Use Always Encrypted
Section titled “Use Always Encrypted”For sensitive columns:
CREATE COLUMN MASTER KEY CMK1WITH ( KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE', KEY_PATH = 'CurrentUser/my/cert_hash');
ALTER TABLE customersALTER COLUMN ssn VARCHAR(11) ENCRYPTED WITH ( COLUMN_ENCRYPTION_KEY = CEK1, ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256');Connection Pooling
Section titled “Connection Pooling”Querri uses connection pooling:
- Min Pool Size: 1
- Max Pool Size: 10
- Connection Lifetime: 300 seconds
- Connection Timeout: 30 seconds
SQL Server Versions
Section titled “SQL Server Versions”Tested and supported:
- SQL Server 2022 ✓
- SQL Server 2019 ✓
- SQL Server 2017 ✓
- SQL Server 2016 ✓
- Azure SQL Database ✓
- Azure SQL Managed Instance ✓
Support
Section titled “Support”SQL Server Resources
Section titled “SQL Server Resources”- SQL Server Documentation: docs.microsoft.com/sql
- Azure SQL Documentation: docs.microsoft.com/azure/sql-database
- SQL Server Forums: social.technet.microsoft.com/Forums/sqlserver
Querri Support
Section titled “Querri Support”- Email: support@querri.com
- Documentation: /guides/connectors/