Skip to main content

例を使ってSnowflakeストアドプロシージャを学びましょう

sales
Image by Gerd Altmann from Pixabay


データベースの操作において、反復的なタスクや複雑なロジックの実行は、時間と労力を要する作業になりがちです。Snowflakeストアドプロシージャは、こうした課題を解決するための強力な機能であり、SQLクエリを拡張して、より効率的かつ安全なデータ処理を実現します。

本稿では、Snowflakeストアドプロシージャの基本的な概念から、JavaScript、Python、そしてSnowflake Scripting (SQL)といった複数のプログラミング言語を使った作成方法、さらにはセキュリティ対策まで、実践的な知識を提供します。

小売業におけるキャンペーン管理を例に、県名に応じてキャンペーン情報と割引率を一括更新するストアドプロシージャを実装します。

ストアドプロシージャと言うのは

ストアドプロシージャを関数の一つ種類と考えてもいいです。ストアドプロシージャを記述して、 SQL を実行する手続き型コードでシステムを拡張できます。ストアドプロシージャを作成すると、何度でも再利用できます。 値を明示的に返すことが許可されていますが、必須ではないです。ストアドプロシージャを実行するロールの権限だけではなく、プロシージャを所有するロールの権限でも実行出来ます。

サポートされている言語:

  • Java
  • JavaScript
  • Python
  • Scala
  • Snowflake Scripting (SQL)

ストアドプロシージャの形:

CREATE OR REPLACE PROCEDURE プロシージャ名(arguments argumentsのタイプ)
RETURNS レターんタイプ
LANGUAGE 言語 -- (例:python, JavaScript等)
-- RUNTIME_VERSION = '3.8' (言語がpython, java, scalaなら必要 )
-- PACKAGES = ('snowflake-snowpark-python') (言語がpython, java, scalaなら必要 )
-- HANDLER = 'run' (言語がpython, java, scalaなら必要 )
EXECUTE AS -- (CALLERか OWNER)
AS
$$
ロジック
$$;

SQL で書いたストアドプロシージャの例:

CREATE OR REPLACE PROCEDURE concatenate_strings(
    first_arg VARCHAR,
    second_arg VARCHAR,
    third_arg VARCHAR DEFAULT ' default_argument '
)
  RETURNS VARCHAR
  LANGUAGE SQL
  AS
  $$
  BEGIN
    RETURN first_arg || second_arg || third_arg;
  END;
  $$;

プロシージャのロジックはハンドラーと言わります。

ストアドプロシージャを呼び方:

CALL procedure名(argument);

Snowflake が関数もストアドプロシージャもサポートしています。 一つの違いさは関数をSelectと一緒に使いますが、ストアドプロシージャをselectと一緒に使えないです。 だから、ストアドプロシージャは値を明示的に返す必要がないです。

関数をクエリ結果の操作などの読み取り操作に使った方がいいです。関数は、テーブル、スキーマ、データベース構造などを変更または作成してはなりません。また、関数はデータを更新または削除して基礎となるデータを変更してはなりません。

ストアドプロシージャを以下のようなDDLまたはDMLデータベース操作の実行が必要に時に、使った方がいいです。

  • テーブルを作成、schemaを削除、 ユーザーの追加など、DDL を含む管理タスク。
  • DML コマンド(例: INSERT、 DELETE、 UPDATE ステートメント)

ストアドプロシージャを三つの方法で呼べます。 上の例で作成したconcatenate_stringストアドプロシージャを呼んでみましょう。

CALL concatenate_strings('one_v0', 'two_v0', 'three_v0');

CALL concatenate_strings(first_arg => 'one_v1', second_arg => 'two_v1', third_arg => 'three_v1');

-- 順番が変わったいます。
CALL concatenate_strings(third_arg => 'three_v2', first_arg => 'one_v2', second_arg => 'two_v2');

-- 三番目のparameterがデフォルトの価値あるので、二つだけのArgumentを使うのはOkです。
CALL concatenate_strings('one_v3', 'two_v3');

Security

ハンドラーコードは、制限されたエンジン内で実行されます。ハンドラーコードが大量のメモリを消費すると、エラーが返されます。ハンドラーの完了に時間がかかりすぎると、Snowflake は SQL ステートメントを強制終了し、ユーザーにエラーを返します。これにより、無限ループなどのエラーの影響およびコストが制限されます。 ハンドラーは外部ライブラリの機能を使用できますが、Snowflake のセキュリティ制限により、ファイルへの書き込みなど、一部の機能が無効になります。 ストアドプロシージャはアトミックではありません。ストアドプロシージャ内の 1 つのステートメントが失敗した場合、ストアドプロシージャ内の他のステートメントは必ずしもロールバックされるとは限りません。

ストアドプロシージャは、 SQL ステートメントを動的に作成して実行できます。ただし、これにより、特にパブリックまたは信頼できないソースからの入力を使用して SQL ステートメントを作成する場合、 SQL インジェクション攻撃が可能になります。

テキストを連結するのではなく、パラメーターをバインドすることにより、 SQL インジェクション攻撃のリスクを最小限に抑えることができます。

バインドの例:

let my_variable = 'variable' + '_value';
let statement = snowflake.createStatement({
    sqlText: 'INSERT INTO table2 (col1, col2) VALUES (?, ?);',
    binds: ['LiteralValue1', my_variable],
});

練習

ストアドプロシージャを何かと使う方法を学びました、今学んだ事を練習しましょう。 この練習で JavaScript, Python と SQL を利用し、同じ事をする三つのストアドプロシージャ作成します。

環境とタスクの説明: 次の事を想像してください。あなたは日本国内各県に複雑の店がある大きな小売会社で働いています。あなたの会社は良く色々な県で販売キャンペーンをやります。各店の店名と県名、販売キャンペーンが行おっているかないか、販売キャンペーンが行おっているば、割引のデータを保存するテーブルがあります。毎回会社ある県で販売キャンペーンが始めり、それとも、終了した時に、テーブルを更新するのは面倒くさいので、あなたはテーブルを更新するストアドプロシージャを開発したいです。

データをの準備

キャンペーンテーブルを作成します。

create table if not exists campaigns_table(
  id INT,
  store_name VARCHAR,
  prefecture VARCHAR,
  campaign BOOLEAN DEFAULT false,
  discount INT DEFAULT 0
);

キャンペーンテーブルにデータを入力します。

INSERT INTO campaigns_table (id, store_name, prefecture)
VALUES
(1, 'Store A', 'Hokkaido'),
(2, 'Store B', 'Aomori'),
(3, 'Store C', 'Iwate'),
(4, 'Store D', 'Miyagi'),
(5, 'Store E', 'Akita'),
(6, 'Store F', 'Yamagata'),
(7, 'Store G', 'Fukushima'),
(8, 'Store H', 'Ibaraki'),
(9, 'Store I', 'Tochigi'),
(10, 'Store J', 'Gunma'),
(11, 'Store K', 'Saitama'),
(12, 'Store L', 'Chiba'),
(13, 'Store M', 'Tokyo'),
(14, 'Store N', 'Kanagawa'),
(15, 'Store O', 'Niigata');
もっとデータを入力したいなら、クリックしてください。
INSERT INTO campaigns_table (id, store_name, prefecture)
VALUES
(16, 'Store P', 'Toyama'),
(17, 'Store Q', 'Ishikawa'),
(18, 'Store R', 'Fukui'),
(19, 'Store S', 'Yamanashi'),
(20, 'Store T', 'Nagano'),
(21, 'Store U', 'Gifu'),
(22, 'Store V', 'Shizuoka'),
(23, 'Store W', 'Aichi'),
(24, 'Store X', 'Mie'),
(25, 'Store Y', 'Shiga'),
(26, 'Store Z', 'Kyoto'),
(27, 'Store AA', 'Osaka'),
(28, 'Store AB', 'Hyogo'),
(29, 'Store AC', 'Nara'),
(30, 'Store AD', 'Wakayama'),
(31, 'Store AE', 'Tottori'),
(32, 'Store AF', 'Shimane'),
(33, 'Store AG', 'Okayama'),
(34, 'Store AH', 'Hiroshima'),
(35, 'Store AI', 'Yamaguchi'),
(36, 'Store AJ', 'Tokushima'),
(37, 'Store AK', 'Kagawa'),
(38, 'Store AL', 'Ehime'),
(39, 'Store AM', 'Kochi'),
(40, 'Store AN', 'Fukuoka'),
(41, 'Store AO', 'Saga'),
(42, 'Store AP', 'Nagasaki'),
(43, 'Store AQ', 'Kumamoto'),
(44, 'Store AR', 'Oita'),
(45, 'Store AS', 'Miyazaki'),
(46, 'Store AT', 'Kagoshima'),
(47, 'Store AU', 'Okinawa'),
(48, 'Store AV', 'Hokkaido'),
(49, 'Store AW', 'Aomori'),
(50, 'Store AX', 'Iwate'),
(51, 'Store AY', 'Miyagi'),
(52, 'Store AZ', 'Akita'),
(53, 'Store BA', 'Yamagata'),
(54, 'Store BB', 'Fukushima'),
(55, 'Store BC', 'Ibaraki'),
(56, 'Store BD', 'Tochigi'),
(57, 'Store BE', 'Gunma'),
(58, 'Store BF', 'Saitama'),
(59, 'Store BG', 'Chiba'),
(60, 'Store BH', 'Tokyo'),
(61, 'Store BI', 'Kanagawa'),
(62, 'Store BJ', 'Niigata'),
(63, 'Store BK', 'Toyama'),
(64, 'Store BL', 'Ishikawa'),
(65, 'Store BM', 'Fukui'),
(66, 'Store BN', 'Yamanashi'),
(67, 'Store BO', 'Nagano'),
(68, 'Store BP', 'Gifu'),
(69, 'Store BQ', 'Shizuoka'),
(70, 'Store BR', 'Aichi'),
(71, 'Store BS', 'Mie'),
(72, 'Store BT', 'Shiga'),
(73, 'Store BU', 'Kyoto'),
(74, 'Store BV', 'Osaka'),
(75, 'Store BW', 'Hyogo'),
(76, 'Store BX', 'Nara'),
(77, 'Store BY', 'Wakayama'),
(78, 'Store BZ', 'Tottori'),
(79, 'Store CA', 'Shimane'),
(80, 'Store CB', 'Okayama'),
(81, 'Store CC', 'Hiroshima'),
(82, 'Store CD', 'Yamaguchi'),
(83, 'Store CE', 'Tokushima'),
(84, 'Store CF', 'Kagawa'),
(85, 'Store CG', 'Ehime'),
(86, 'Store CH', 'Kochi'),
(87, 'Store CI', 'Fukuoka'),
(88, 'Store CJ', 'Saga'),
(89, 'Store CK', 'Nagasaki'),
(90, 'Store CL', 'Kumamoto'),
(91, 'Store CM', 'Oita'),
(92, 'Store CN', 'Miyazaki'),
(93, 'Store CO', 'Kagoshima'),
(94, 'Store CP', 'Okinawa'),
(95, 'Store CQ', 'Hokkaido'),
(96, 'Store CR', 'Aomori'),
(97, 'Store CS', 'Iwate'),
(98, 'Store CT', 'Miyagi'),
(99, 'Store CU', 'Akita'),
(100, 'Store CV', 'Yamagata'),
(101, 'Store CW', 'Fukushima'),
(102, 'Store CX', 'Ibaraki'),
(103, 'Store CY', 'Tochigi'),
(104, 'Store CZ', 'Gunma'),
(105, 'Store DA', 'Saitama'),
(106, 'Store DB', 'Chiba'),
(107, 'Store DC', 'Tokyo'),
(108, 'Store DD', 'Kanagawa'),
(109, 'Store DE', 'Niigata'),
(110, 'Store DF', 'Toyama'),
(111, 'Store DG', 'Ishikawa'),
(112, 'Store DH', 'Fukui'),
(113, 'Store DI', 'Yamanashi'),
(114, 'Store DJ', 'Nagano'),
(115, 'Store DK', 'Gifu'),
(116, 'Store DL', 'Shizuoka'),
(117, 'Store DM', 'Aichi'),
(118, 'Store DN', 'Mie'),
(119, 'Store DO', 'Shiga'),
(120, 'Store DP', 'Kyoto'),
(121, 'Store DQ', 'Osaka'),
(122, 'Store DR', 'Hyogo'),
(123, 'Store DS', 'Nara'),
(124, 'Store DT', 'Wakayama'),
(125, 'Store DU', 'Tottori'),
(126, 'Store DV', 'Shimane'),
(127, 'Store DW', 'Okayama'),
(128, 'Store DX', 'Hiroshima'),
(129, 'Store DY', 'Yamaguchi'),
(130, 'Store DZ', 'Tokushima'),
(131, 'Store EA', 'Kagawa'),
(132, 'Store EB', 'Ehime'),
(133, 'Store EC', 'Kochi'),
(134, 'Store ED', 'Fukuoka'),
(135, 'Store EE', 'Saga'),
(136, 'Store EF', 'Nagasaki'),
(137, 'Store EG', 'Kumamoto'),
(138, 'Store EH', 'Oita'),
(139, 'Store EI', 'Miyazaki'),
(140, 'Store EJ', 'Kagoshima'),
(141, 'Store EK', 'Okinawa'),
(142, 'Store EL', 'Hokkaido'),
(143, 'Store EM', 'Aomori'),
(144, 'Store EN', 'Iwate'),
(145, 'Store EO', 'Miyagi'),
(146, 'Store EP', 'Akita'),
(147, 'Store EQ', 'Yamagata'),
(148, 'Store ER', 'Fukushima'),
(149, 'Store ES', 'Ibaraki'),
(150, 'Store ET', 'Tochigi'),
(151, 'Store EU', 'Gunma'),
(152, 'Store EV', 'Saitama'),
(153, 'Store EW', 'Chiba'),
(154, 'Store EX', 'Tokyo'),
(155, 'Store EY', 'Kanagawa'),
(156, 'Store EZ', 'Niigata'),
(157, 'Store FA', 'Toyama'),
(158, 'Store FB', 'Ishikawa'),
(159, 'Store FC', 'Fukui'),
(160, 'Store FD', 'Yamanashi'),
(161, 'Store FE', 'Nagano'),
(162, 'Store FF', 'Gifu'),
(163, 'Store FG', 'Shizuoka'),
(164, 'Store FH', 'Aichi'),
(165, 'Store FI', 'Mie'),
(166, 'Store FJ', 'Shiga'),
(167, 'Store FK', 'Kyoto'),
(168, 'Store FL', 'Osaka'),
(169, 'Store FM', 'Hyogo'),
(170, 'Store FN', 'Nara'),
(171, 'Store FO', 'Wakayama'),
(172, 'Store FP', 'Tottori'),
(173, 'Store FQ', 'Shimane'),
(174, 'Store FR', 'Okayama'),
(175, 'Store FS', 'Hiroshima'),
(176, 'Store FT', 'Yamaguchi'),
(177, 'Store FU', 'Tokushima'),
(178, 'Store FV', 'Kagawa'),
(179, 'Store FW', 'Ehime'),
(180, 'Store FX', 'Kochi'),
(181, 'Store FY', 'Fukuoka'),
(182, 'Store FZ', 'Saga'),
(183, 'Store GA', 'Nagasaki'),
(184, 'Store GB', 'Kumamoto'),
(185, 'Store GC', 'Oita'),
(186, 'Store GD', 'Miyazaki'),
(187, 'Store GE', 'Kagoshima'),
(188, 'Store GF', 'Okinawa'),
(189, 'Store GG', 'Hokkaido'),
(190, 'Store GH', 'Aomori'),
(191, 'Store GI', 'Iwate'),
(192, 'Store GJ', 'Miyagi'),
(193, 'Store GK', 'Akita'),
(194, 'Store GL', 'Yamagata'),
(195, 'Store GM', 'Fukushima'),
(196, 'Store GN', 'Ibaraki'),
(197, 'Store GO', 'Tochigi'),
(198, 'Store GP', 'Gunma'),
(199, 'Store GQ', 'Saitama'),
(200, 'Store GR', 'Chiba');


ストアドプロシージャを三つの言語で作りましょう

条件:現在は会社でキャンペーンが行おっていませんが、北海道でキャンペーンが始める予定です。

JavaScript

let sql_cmd = "select * from table1 where year < 2016";
let statement = snowflake.createStatement({sqlText: sql_cmd});
let result_set = statement.execute();
  • Snowflake の JavaScript ストアドプロシージャ環境ではsnowflakeというオブジェクトは、宣言なしで存在する特別なオブジェクトです。オブジェクトは各ストアドプロシージャのコンテキスト内で提供され、 API を公開して、サーバーと対話できるようにします。つまり、SQL コードを実行するに、このsnowflakeオブジェクトを利用します。

  • JavaScript を使用するストアドプロシージャの場合、ステートメントの SQL 部分の識別子(引数名など)は自動的に大文字に変換されます。

  • Snowflake ストアドプロシージャの API は同期的です。

じゃあ、campaigns_tableテーブルを更新するストアドプロシージャを作りましょう。

CREATE OR REPLACE PROCEDURE TOGGLE_DISCOUNTS_JS(REGION STRING, ONCAMPAIGN BOOLEAN, DISCOUNT FLOAT DEFAULT 0)
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
AS
$$
    if((ONCAMPAIGN && DISCOUNT <= 0) || (!ONCAMPAIGN && DISCOUNT != 0))
    {
      throw new Error('Input arguments are wrong');
    }
    const tableName = 'campaigns_table';
    const campaingColumn = 'CAMPAIGN';
    const discountColumn = 'DISCOUNT';
    const regionLowerCase = REGION.toLowerCase();
    const regionUpperCase = regionLowerCase.toUpperCase();
    const regionCapitilized = regionUpperCase.charAt(0) + regionLowerCase.substring(1);
   
    const statement = snowflake.createStatement({
      sqlText: `UPDATE ${tableName} SET ${campaingColumn} = :1, ${discountColumn} = :2 
                WHERE prefecture IN (:3, :4, :5, :6);`,
      binds:[ONCAMPAIGN, DISCOUNT, REGION, regionLowerCase, regionUpperCase, regionCapitilized]
      });
    statement.execute();
    return `${statement.getNumRowsUpdated()} 行が更新されました。`;
$$;

使う方: もし、ある県で販売キャンペーンが始まった場合は、その県の県名、TRUE(キャンペーンが行おっていると言う意味)、と割引数字をストアドプロシージャに出します。

もし、販売キャンペーンが終わった場合は、その県の県名、とFALSE(キャンペーンが行おっていないと言う意味)をストアドプロシージャに出します。

このストアドプロシージャを呼ぶ時に県名を大き文字で書いても、小さ文字で書いても, 大文字と小文字を混ぜて書いても、問題なく動くようにしました。

今は Hokkaido でキャンペーン始まりました。 上のストアドプロシージャを呼んでください。

CALL TOGGLE_DISCOUNTS_JS('HOKKAIDO', TRUE, 20);

上のストアドプロシージャを呼んだ後、テーブルが更新されたか、確認してみてください。

SELECT *
FROM campaigns_table;
-- or
SELECT *
FROM campaigns_table
WHERE prefecture = 'Hokkaido';

Python

JavaScript ストアドプロシージャ環境ではsnowflakeオブジェクトがあったように、python ストアドプロシージャ環境ではsessionオブジェクトがあります。SQL コードを実行するに、このsessionオブジェクトを利用します。

JavaScript ストアドプロシージャと同じ結果を達成するストアドプロシージャを python でやってみましょう。

CREATE OR REPLACE PROCEDURE toggle_discounts_py(region STRING, is_discounted STRING, discount NUMBER DEFAULT 0)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'main'
AS
$$
def main(session, region, is_discounted, discount = 0):
    if (is_discounted and discount <= 0) or (not is_discounted and discount != 0):
      raise Exception('Input arguments are wrong')
    table_name = 'campaigns_table'
    campaing_column = 'CAMPAIGN'
    discount_column = 'DISCOUNT'
    region_lower = region.lower()
    region_upper = region_lower.upper()
    region_capitilized = region_lower.capitalize()
    sql_command = f"UPDATE {table_name} SET {campaing_column} = :1, {discount_column} =:2 WHERE prefecture IN (:3, :4, :5, :6);"
    result = session.sql(sql_command, [is_discounted, discount, region, region_lower, region_upper, region_capitilized]).collect()
    return result[0]
$$;

今は Tokyo でもキャンペーンが始まりました。 上のストアドプロシージャを呼んでください。

CALL TOGGLE_DISCOUNTS_PY('Tokyo', TRUE, 10);

上のストアドプロシージャを呼んだ後、テーブルが更新されたか、確認してみてください。

SELECT *
FROM campaigns_table;
-- or
SELECT *
FROM campaigns_table
WHERE prefecture = 'Tokyo';
Python のストアドプロシージャの強み

Python のストアドプロシージャは特に Pandas ようなライブラリを使って、データ分析する為に役に立ちます。

以下のクエリーから Snowflake で使える Python のライブラリリストをクエリー出来ます。

select * from
information_schema.packages
where language = 'python';

Snowflake Scripting (SQL)

上のストアドプロシージャと同じ結果を達成するストアドプロシージャを SQL でやってみましょう。

CREATE OR REPLACE PROCEDURE toggle_discount_sql(
    region STRING,
    is_discounted STRING,
    discount NUMBER DEFAULT 0)
RETURNS VARCHAR NOT NULL
LANGUAGE SQL
AS
$$
  DECLARE
  invalid_arguments EXCEPTION (-20003, 'Input arguments are wrong');
  BEGIN
  IF ((is_discounted and discount <= 0) or (not is_discounted and discount != 0) or (discount > 100)) THEN
    RAISE invalid_arguments;
  END IF;
  UPDATE campaigns_table
  SET CAMPAIGN = :is_discounted, DISCOUNT = :discount
  WHERE PREFECTURE IN (:region, UPPER(:region), LOWER(:region), INITCAP(:region));
  RETURN 'Rows Updated: ' || SQLROWCOUNT;
  END;
$$;

今は Tokyo でキャンペーンが終わりました。 上のストアドプロシージャを呼んでください。

CALL toggle_discount_sql(
    REGION => 'ToKyO',
    is_discounted => FALSE
    );

上のストアドプロシージャを呼んだ後、テーブルが更新されたか、確認してみてください。

SELECT *
FROM campaigns_table;
-- or
SELECT *
FROM campaigns_table
WHERE prefecture = 'Tokyo';

結論

ストアド プロシージャは強力な機能です。ハンドラ/ロジックは、さまざまな言語のいずれかで記述で、言語の選択に正しい選択や間違った選択はありません。どの言語に最も得意なら、その言語を使ってください。

Snowflake の機能についてもっと学びたいなら以下の記事をご覧ください。

Comments

Popular posts from this blog

Introduction to SQLFluff: How to make your SQL code clean and error-free

Image by Jake Aldridge from Pixabay You know oftentimes, the cause of runtime or compile errors and hours of debugging agony is all due to simply a missing semicolon. Have you ever had such experience? If you had, you are not alone. There are two ways to avoid these unfortunate situations: either become a perfect developer who never makes mistakes, or use helpful tools such as linters that can catch these errors early on. I am nowhere near being a perfect developer who never makes a mistake. In fact, I'm probably the opposite of a perfect developer, so even if I wanted to, I wouldn’t be able to teach you how to become a perfect developer. But what I can teach you is using linters. A Wikipedia defines a linter as a "static code analysis tool used to flag programming errors, bugs, stylistic errors and suspicious constructs." If you're not convinced yet on using linters, consider this scenario: in a large project with multiple members, different people tend to ...

How To Use KeePassXC Cli

There are similarly named programs: KeePass, KeePassX and KeePassXC (many of which are each others’ forks). Program Condition KeePass primarily for Windows. KeePassX no longer actively maintained. KeePassXC actively maintained and runs natively on Linux, macOS and Windows . Note: GUI version of the KeePassXC has more features than cli version. GUI version has variety of shortcuts as well. Regarding how to use GUI version of the KeePassXC, visit Getting Started Guide . Below features are available only in GUI version. Setting “Name” and “Description” fields of passwords database. Nesting Groups. Creating entry attributes ( open issue ). Adding Timed One-Time Passwords (TOTP). Adding entry with the same title as existing entry. KeePassXC stores all the passwords in passwords database. A passwords database (hereafter referred to as database) is an (encrypted) binary file. It can have any or no extension, but the .kdbx extension is commonly used. The ...

Git squash merge explained

There are many ways to integrate changes in git: regular / normal git merge, git squash merge, git rebase etc. This article explains git squash merge by comparing it to regular merge. Let’s use below example: In the repository with default main branch, after two commits, a new feature branch is created. Some work happened in feature branch. feature branch now has 2 commits that it shares with main branch, and three exclusive commits (exists only in feature branch). In the meantime, others worked on main branch and added two new commits (exists only in main branch). git log output of the main branch: c72d4a9 ( HEAD - > main ) fourth commit on main 2c3dd61 third commit on main 0c2eec3 second commit on main 9b968e8 first commit on main git log output of the feature branch: 786650f ( HEAD - > feature ) third commit on feature 21cbaf1 second commit on feature 677bc7f first commit on feature 0c2eec3 second commit on main 9b968e8 first commit on mai...

Snowflake Load History vs Copy History: 7 differences

Image by Icons8_team from Pixabay Tracking data loads in Snowflake is crucial to maintaining data health and performance. Load History and Copy History are features that provide valuable information about past data loads. Understanding these features can help you efficiently troubleshoot, audit, and analyze performance. You might be wondering why two functions exist to achieve the same goal, what are the differences, which one I am supposed to use and when? In this article we will provide you with all the answers. So, let's learn what are the differences and when to use which! Load History vs Copy History: 7 differences Differences 1 and 2: views vs table function and Account Usage vs information Schema Here things get little confusing, bare with me, there are two Load History views, a view that belongs to Information Schema and a view that belongs to Account Usage schema . As for Copy History, there are Copy History table function of Information schema and a Copy H...

WinMerge のセットアップと使う方

WinMerge は、Windows 用のオープン ソースの差分およびマージ ツールです。WinMerge は、フォルダーとファイルの両方を比較し、違いを理解して扱いやすい視覚的なテキスト形式で表示します。この記事でWinMerge のセットアップと使う方を教えます。 source: https://winmerge.org WinMerge をダウンロード WinMerge のウェブサイト に行って、「WinMerge-2.16.44-x64-Setup.exe」ボタンを押し、WinMerge 2.16 をダウンロードしてください。 WinMerge をインストール ダウンロードされたソフトウェアをクリックし、ポップアップ画面で「Next」を押してください 「Languages」部分をスクロールダウンし、「Japanese menus and dialogs」を選択し、「Next」ボタンを押してください ターミナル等からも WinMerge をアクセス出来ようにする為に「Add WinMerge folder to your system path」オプションを選択し、希望によって他のオプション選択してください 「Enable Explorer context menu Integration」オプションを選択したら、フォルダ/ファイルを右キリックし、コンテクストメニューから WinMerge を開くようになります。 「Install」ボタンを押し、「Next」ボタンを押し、その後、「Finish」ボタンを押してください 言語を日本語にする もし WinMerge の言語が日本語じゃなくて、英語なら、「Edit」タブから「Options」を押してください。 ポップアップ画面で右側の下にある「Languages」と言うドロップダウンメニューから日本語を選択し、「OK」ボタンを押してください WinMerge を使う方 「ファイル」タッブから「開く」を押し 参照ボタンを押し、比較したいフォルダ・ファイルを指定 比較したいフォルダを指定する方法: ポップアップ画面から対象のフォルダーを選択し、「Open」を押してくだい 何も選択しないで、「Open」を押してくだい 右側下にある「比較」ボタンを押し ...

From Generic to Genius: Fine-tuning LLMs for Superior Accuracy in Snowflake

TL;DR: Cortex Fine-tuning is a fully managed service that lets you fine-tune popular LLMs using your data, all within Snowflake. While large language models (LLMs) are revolutionizing various fields, their "out-of-the-box" capabilities might not always align perfectly with your specific needs. This is where the power of fine-tuning comes into play. As it will be explained in this article, this feature empowers you to take a base LLM and customize it to excel in your particular domain. Here's the brief summary of why you might want to leverage Snowflake's fine-tuning capabilities: Unlocking Domain Expertise : Pre-trained LLMs are trained on massive, general datasets. Fine-tuning allows you to build upon this foundation and train the LLM further using data specific to your field, such as legal documents, medical records, or financial data. This empowers the LLM to understand complex terminology and patterns unique to your domain, leading to more accurate a...

Streamline Your Workflow: Send Snowflake Alerts to Slack

Do you know integrating Snowflake and Slack can make your life as a data engineer much easier?  Here's why: Real-time error catching and debugging : Instead of constantly checking logs for errors, you can set up Snowflake to automatically ping you in a Slack channel when something goes wrong. This is like having a dedicated assistant who watches for errors in your code and immediately lets you know so you can fix them faster. This is achieved through the use of webhooks, which are essentially automated HTTP requests that Snowflake sends to Slack when triggered by an event. Keep everyone in the loop : Slack integration also means you can keep your entire team informed about the status of data pipelines and other processes. You can configure Snowflake to send notifications to a shared channel whenever a pipeline completes, fails, or encounters an issue. This keeps everyone on the same page and avoids unnecessary status update meetings. This integration turns Slack ...

脱初心者! Git ワークフローを理解して開発効率アップ

Git – チーム開発に必須のバージョン管理システムですが、その真価を発揮するにはワークフローの理解が欠かせません。 色々な人は Git の使い方を良く知っていますが、Git を仕事やワークフローに統合する方法を余り良く知らない人もいます。本記事では、Git をワークフローに組み込むことで、開発プロセスがどのように効率化され、チーム全体のパフォーマンスが向上するのかを解説します。Centralized Workflow から Forking Workflow まで、代表的な 9 つのワークフローの特徴を分かりやすく紹介します。それぞれのメリット・デメリット、そして最適なユースケースを理解することで、あなたのプロジェクトに最適なワークフローを選択し、開発をスムーズに進めましょう! Centralized Workflow Feature branching/GitHub Flow Trunk Based Flow Git Feature Flow Git Flow Enhanced Git Flow One Flow GitLab Flow Forking Workflow 分かりやすくするために、同じコンセプトを説明するに一つ以上の図を使った場合があります。 Centralized Workflow 説明: 集中化ワークフローではプロジェクトにおけるすべての変更の単一の入力箇所として中央リポジトリを使用します。デフォルトの開発用ブランチは main と呼ばれ、すべての変更がこのブランチにコミットされます。 集中化ワークフローでは main 以外のブランチは不要です。チームメンバー全員がひとつのブランチで作業し、変更を直接中央リポジトリにプッシュします。 メリット: SVN のような集中型バージョン管理システムから移行する小規模チームに最適。 デメリット: お互いのコードが邪魔になり (お互いの変更を上書きするように)、プロダクション環境にバグをい入れる可能性が高くて、複数のメンバいるチームでこのフローを使いにくい。 地図: graph TD; A[Central Repository] -->|Clone| B1[Developer A's Local Repo] A --...

ワークフローの合理化:Snowflake アラートを Slack に送信する

Snowflake と Slack の連携でデータエンジニアの仕事がはかどる! Snowflake と Slack を連携させると、データエンジニアの業務効率が大幅に向上します。 その理由を見ていきましょう。 リアルタイムなエラー検知とデバッグ : これまでのようにログを常に監視しなくても、Snowflake でエラーが発生した場合に Slack チャンネルに自動通知を送信するように設定できます。これは、コードのエラーを監視し、すぐに知らせてくれる専任のアシスタントがいるようなものです。迅速な問題解決が可能になります。これは、Webhook を使用することで実現します。Webhook とは、イベントをトリガーとして Snowflake から Slack に送信される自動 HTTP リクエストです。 チーム全体の情報共有 : Slack 連携により、データパイプラインなどの処理状況をチーム全体に共有することもできます。パイプラインが完了、失敗、または問題が発生した場合に、共有チャンネルに通知を送信するように Snowflake を設定できます。これにより、全員が状況を把握できるようになり、不要な進捗確認会議を減らすことができます。 この連携により、Slack がデータワークフロー管理の強力なハブとなり、データエンジニアの業務をよりシンプルかつ生産的にします。 SnowflakeとSlackを統合する方法 Snowflake の NOTIFICATION INTEGRATION と言う機能と Slack の Webhook を利用し Snowflake から Slack にメッセージを送る事が出来ます。 同じ方法を使って、Snowflake から Microsoft Teams と PagerDuty にもメッセージを送るのは可能です。 Slack の使う方の概要が必要なら、この 動画 を見てください。 Webhook は http リクエストです。これは API 呼び出しで、リバース API または Push API と呼ばれることもあります。Webhook の特徴は、何らかのイベントが発生したときにクライアントがサーバーにコールバック (http リクエストを送信) するように指示することです。...